Erhalten einer tcsh-dextract-ähnlichen Pushd-Funktionalität in Bash

Erhalten einer tcsh-dextract-ähnlichen Pushd-Funktionalität in Bash

Ich liebe bash(4.1.2(1)-Release), bevorzuge aber die Implementierungsweise tcshbei pushd +Naktivierter dextractOption so sehr, dass ich mich bashdeshalb weigere, sie als meine Standard-Shell zu verwenden. Hat jemand einen dextract-ähnlichen Verzeichnisstapel-Befehlssatz implementiert bashoder habe ich vielleicht noch nicht herausgefunden, wie ich es dazu bringen kann, sich bei aktivierter Option bashwie zu verhalten ?tcshdextract

Der Knackpunkt: Die Reihenfolge, die bashder Verzeichnisstapel nach einem hinterlässt pushd +N. Zum Beispiel:

$ 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

Warum rotiert bash(und standardmäßig tcsh) die Positionen aller anderen Verzeichnisse, wenn ich ein mache pushd +1? Warum ist das nützlich? (Vielleicht würde ich das Verhalten zu schätzen wissen und mich daran gewöhnen, wenn es mir jemand erklären würde.) Vergleichen Sie tcshmit dextract, das es einfach extrahiert und oben platziert:

% 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 

Beachten Sie, dass die restliche Reihenfolge der Verzeichnisse unverändert bleibt. Ich halte das für wichtig, da es für mich einfacher ist, den Überblick zu behalten, wenn die Reihenfolge nicht geändert wird, und ich so nicht immer dirsnach dem gewünschten Verzeichnis suchen muss.

Wenn ich es versuchen würde, wo würde ich anfangen? Ich sehe, dass es eine Variable gibt DIRSTACK, aber sie ist nicht korrekt (sie ist leer, wenn der Stapel vier Einträge hat), obwohl eine Änderung den Stapel ändert (allerdings nicht korrekt).

Antwort1

Nach einiger Arbeit und Inspiration habe ich mein Problem gelöst:

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

verwandte Informationen