Obtendo funcionalidade pushd semelhante a tcsh dextract no bash

Obtendo funcionalidade pushd semelhante a tcsh dextract no bash

Eu adoro bash(4.1.2(1)-release) mas prefiro fortemente a forma como tcshé implementado pushd +Ncom a dextractopção habilitada, tanto que me recuso a usar bashcomo meu shell padrão por causa disso. Alguém implementou um dextractconjunto de comandos de pilha de diretórios semelhante a bashou talvez eu não tenha descoberto como persuadir basha se comportar como tcshativado dextract?

O ponto crítico: a ordem que bashdeixa a pilha de diretórios depois de um arquivo pushd +N. Por exemplo:

$ 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

Por que bash(e o padrão tcsh) gira as posições de todos os outros diretórios quando eu faço um pushd +1? Por que isso é útil? (Talvez se alguém explicasse, eu apreciaria o comportamento e me acostumaria com ele.) Compare com tcshwith dextract, que apenas extrai e coloca no topo:

% 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 

Observe que a ordem restante dos diretórios permanece intacta. Considero isso importante porque é mais fácil manter o controle em minha mente quando o pedido não é alternado e, portanto, não preciso ficar sempre dirspesquisando o diretório que desejo.

Se eu tentasse, por onde começaria? Vejo que há uma variável DIRSTACK, mas ela não está correta (está vazia quando a pilha tem quatro entradas), embora alterá-la altere a pilha (embora não corretamente).

Responder1

Depois de algum trabalho e inspiração, resolvi meu problema:

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

informação relacionada