Получение функциональности pushd, подобной tcsh dextract, в bash

Получение функциональности pushd, подобной tcsh dextract, в bash

Мне нравится bash(4.1.2(1)-release), но я решительно предпочитаю способ tcshреализации pushd +Nс dextractвключенной опцией, настолько, что я отказываюсь использовать ее bashв качестве своей оболочки по умолчанию из-за этого. Кто-нибудь реализовал dextractнабор команд стека каталогов -like bashили, может быть, я не понял, как заставить bashвести себя как tcshс dextractвключенной?

Камень преткновения: порядок, при котором bashстек каталогов остается после pushd +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

Почему bash(и default tcsh) меняет позиции всех других каталогов, когда я делаю a pushd +1? Почему это полезно? (Возможно, если бы кто-то объяснил, я бы оценил такое поведение и привык к нему.) Сравните с tcshwith dextract, который просто извлекает его и помещает наверх:

% 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, но она неверна (она пуста, когда в стеке четыре записи), хотя ее изменение изменяет стек (хотя и некорректно).

решение1

После некоторой работы и вдохновения я решил свою проблему:

# 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
}

Связанный контент