web-dev-qa-db-ja.com

bashでtcshdextractのようなプッシュ機能を取得する

私はbash(4.1.2(1)-release)が大好きですが、tcshオプションを有効にしてdextractpushd +Nを実装する方法を強く好みます。そのため、デフォルトのシェルとしてbashを使用することを拒否しました。誰かがdextractのようなコマンドのディレクトリスタックセットをbashに実装したことがありますか、それともbashtcshのように動作させる方法を理解していません。 dextractを有効にしますか?

こだわりのポイント:bashpushd +Nの後にディレクトリスタックを残す順序。例えば:

$ cd /tmp
$ pushd a
/tmp/a /tmp
$ pushd ../b
/tmp/b /tmp/a /tmp
$ pushd ../c
/tmp/c /tmp/b /tmp/a /tmp
$ pushd +1
/tmp/b /tmp/a /tmp /tmp/c

pushd +1を実行すると、bash(およびデフォルトのtcsh)が他のすべてのディレクトリの位置をローテーションするのはなぜですか?なぜこれが便利なのですか? (おそらく誰かが説明した場合、私はその振る舞いに感謝し、それに慣れるかもしれません。)tcshdextractを比較してください。

% set dextract
% cd /tmp
% pushd a
/tmp/a /tmp 
% pushd ../b
/tmp/b /tmp/a /tmp 
% pushd ../c
/tmp/c /tmp/b /tmp/a /tmp 
% pushd +1
/tmp/b /tmp/c /tmp/a /tmp 

ディレクトリの残りの順序は変更されないことに注意してください。順序がローテーションされないときは頭の中で追跡しやすいので、これは重要だと思います。したがって、常にdirsを実行して、必要なディレクトリを検索する必要はありません。

もし私がそれにひびを入れたとしたら、どこから始めればいいですか?変数DIRSTACKがあるようですが、それを変更するとスタックが変更されますが(正しくはありません)、正しくありません(スタックに4つのエントリがある場合は空です)。

1
eewanco

いくつかの作業とインスピレーションの後、私は自分の問題を解決しました:

# dextract-like pushd -- Push $1'st directory to top of stack and shift rest down
function pushd {
    local t
    if [[ $1 =~ ^[-+]?[0-9]+$ ]]; then
        pos=$1
        [[ ${pos} -lt 0 ]] && ((pos=${#DIRSTACK[@]}+${pos}))
        if [[ ${pos} -gt 0 && ${pos} -lt ${#DIRSTACK[@]} ]]; then
            t="${DIRSTACK[$pos]}"
            # This is crufty. You can't put ~ in DIRSTACK, except the
            # Shell will put it into position zero when it refers to your
            # own directory (not anyone else's!). So replace any occurrences.
            DIRSTACK=("" "${DIRSTACK[0]/#~/${HOME}}" "${DIRSTACK[@]:1:${pos}-1}" "${DIRSTACK[@]:${pos}+1}")
            cd "$t"
            builtin dirs -v
        else
            echo "$0: pushd: $1: directory stack index out of range" 1>&2
        fi
    else
        builtin pushd "$@" >/dev/null || return
        cd .
        builtin dirs -v
    fi
}
1
eewanco