Haben wir mehr Geschichte für die CD?

Antworten:

31

Der gesuchte Befehl ist pushdund popd.

Sie könnten ein praktisches Arbeitsbeispiel sehen pushdund popdvon hier .

mkdir /tmp/dir1
mkdir /tmp/dir2
mkdir /tmp/dir3
mkdir /tmp/dir4

cd /tmp/dir1
pushd .

cd /tmp/dir2
pushd .

cd /tmp/dir3
pushd .

cd /tmp/dir4
pushd .

dirs
/tmp/dir4 /tmp/dir4 /tmp/dir3 /tmp/dir2 /tmp/dir1
Ramesh
quelle
1
Es gibt auch den $OLDPWDFall, dass Sie mit demselben Befehl zwischen zwei Verzeichnissen hin- und herschalten möchten, aber ich bin mir nicht sicher, wie Shell-spezifisch und Distributions- / Kernel-spezifisch dies ist.
Mechalynx
4
@ivy_lynx OLDPWDist in allen POSIX-Shells vorhanden, aber für diese Frage, die danach fragt, wie man darüber hinausgeht, ist es nutzlos (die Frage erwähnt bereits, cd -welche Abkürzung für steht cd "$OLDPWD").
Gilles 'SO - hör auf böse zu sein'
2
Gibt es einen Grund, den Sie cd /tmp/dir1; pushd . anstelle von nur verwenden pushd /tmp/dir1?
GnP
@gnp, kein spezieller Grund. Es wurde nur dem Link entnommen, auf den ich in der Antwort verwiesen habe. pushd /tmp/dir1sollte gut funktionieren.
Ramesh
1
Ok, habe gerade meine Neugierde geweckt. Ich möchte Sie Ihre Antwort mit einem tatsächlichen Beispiel vorschlagen verbessern verwenden pushdund popdeinen Verzeichnisbaum hin und her zu durchqueren. Ihre Antwort ist bereits richtig.
GnP
53

Sie haben nicht angegeben, welche Shell Sie verwenden. Lassen Sie dies also eine Ausrede sein, um für zsh zu werben.

Ja, tun wir mehr Geschichte für cd, nämlich cd -2, cd -4usw. Sehr praktisch ist cd -TAB, vor allem mit Komplettierungssystem und Farben aktiviert:

Das habe ich in .zshrc:

setopt AUTO_PUSHD                  # pushes the old directory onto the stack
setopt PUSHD_MINUS                 # exchange the meanings of '+' and '-'
setopt CDABLE_VARS                 # expand the expression (allows 'cd -2/tmp')
autoload -U compinit && compinit   # load + start completion
zstyle ':completion:*:directory-stack' list-colors '=(#b) #([0-9]#)*( *)==95=38;5;12'

Und das Ergebnis:

Bildbeschreibung hier eingeben

jimmij
quelle
4
Bash Bash Bash Bash
Tim
7
OK, ich werde diese Antwort nicht löschen, vielleicht wird es für andere nützlich sein.
Jimmy
23
Sofern die Frage nicht ausdrücklich danach fragt bash, ist dies eine gültige Antwort. Entfernen Sie es nicht.
Liori
Was passiert, wenn das OP seine Frage so bearbeitet, dass sie nur Bash enthält? Ist diese Antwort weiterhin gültig?
Ooker
3
Es sollte erwähnt werden, dass abgesehen davon setopt AUTO_PUSHDkeine der obigen Einstellungen erforderlich ist , um einen allgegenwärtigen Verzeichnisstack mit Fertigstellung in stock zsh zu erhalten. PUSHD_MINUSKehrt den Sinn von cd +und um cd -(Geschmackssache), CDABLE_VARSist für Verzeichnisstapel irrelevant, und der zstylehier angegebene Aufruf fügt der Ausgabe eines Verzeichnisstapelabschlusses einfach Farbe hinzu. Man muss jedoch das Vervollständigungssubsystem mit initialisieren autoload -U compinit && compinit.
WJV
13

Um Ihre Frage zu "more history" zu beantworten. Nein, die cd -Funktion in Bash unterstützt nur ein einziges Verzeichnis, in das Sie zurückkehren können. Wie @Ramesh in seiner Antwort feststellt. Wenn Sie einen längeren Verlauf von Verzeichnissen wünschen, können Sie mit pushdund popdein Verzeichnis speichern oder zu einem vorherigen zurückkehren.

Mit dem dirsBefehl können Sie auch die Liste der aktuell im Stapel befindlichen Elemente anzeigen.

Eine ausführliche Erklärung finden Sie in dieser Antwort mit dem Titel: Wie verwende ich die Befehle pushd und popd? .

slm
quelle
Ich habe einen Verweis aus Ihrer Antwort eingefügt. Ich hoffe es macht dir nichts aus. :)
Ramesh
@ Ramesh - nein, mach weiter.
slm
8

Sie können mein Dienstprogramm dirhistory für bash installieren und verwenden .

Grundsätzlich ist es ein Daemon, der Verzeichnisänderungen von all Ihren Shells sammelt, und ein Cdk-Programm, das den Verlauf anzeigt und es Ihnen ermöglicht, jedes Verzeichnis auszuwählen, zu dem Sie wechseln möchten (Sie sind also nicht auf einen Stapel beschränkt).

cjm
quelle
7

Du hast so viel Geschichte wie du willst:

cd() {
[ "$((${DIRSTACKMAX##*[!0-9]*}0/10))" -gt 0 ] &&
        set -- "$@" "$DIRSTACK"               &&
        DIRSTACK='pwd -P >&3; command cd'     ||
        { command cd "$@"; return; }
_q()    while   case "$1" in (*\'*) :   ;;      (*)
                ! DIRSTACK="$DIRSTACK '$2$1'"   ;;esac
        do      set -- "${1#*\'}" "$2${1%%\'*}'\''"
        done
while   [ "$#" -gt 1 ]
do      case    ${1:---} in (-|[!-]*|-*[!0-9]*) : ;;
        (*)     eval "  set $((${1#-}+1))"' "${'"$#}\""
                eval '  set -- "$2"'" $2"'
                        set -- "${'"$1"'}" "$1"'
        ;;esac; _q "$1"; shift
done
eval "  DIRSTACK=; $DIRSTACK    &&"'
        _q "$OLDPWD"            &&
        DIRSTACK=$DIRSTACK\ $1
        set "$?" "${DIRSTACK:=$1}"'" $1
"       3>/dev/null
[ "$(($#-1))" -gt "$DIRSTACKMAX" ] &&
        DIRSTACK="${DIRSTACK% \'/*}"
unset -f _q; return "$1"
}

Dies ist eine Shell-Funktion, die es jeder POSIX-kompatiblen Shell ermöglichen sollte, eine Historie im zshStile anzubieten cd. Es erledigt all seine Arbeit, ohne eine einzige Subshell aufzurufen, und ich glaube, dass sein Fluss ziemlich gut ist - es scheint, alle Fälle unter moderaten Tests richtig zu behandeln.

Die Funktion versucht, so gut wie möglich mit ihrer Umgebung umzugehen, wobei sie sich auf eine vollständig portable Syntax stützt. Dabei wird nur eine Annahme getroffen, und zwar, dass die $DIRSTACKUmgebungsvariable ihre Eigenschaft ist, mit der sie so zu tun hat, wie sie will.

Es kanonisiert alle Pfade, in denen es speichert, $DIRSTACKund serialisiert sie in einfachen Anführungszeichen. Es stellt jedoch sicher, dass jeder Pfad sicher in Anführungszeichen gesetzt und serialisiert wird, bevor er zum Wert der Variablen hinzugefügt wird, und sollte keine Probleme mit Sonderzeichen jeglicher Art haben . Wenn die $DIRSTACKMAXUmgebungsvariable festgelegt ist, wird sie als Obergrenze für die Anzahl der Pfade verwendet, die im Verlauf beibehalten werden. Andernfalls beträgt die Obergrenze eins.

Wenn Sie die Funktion cdwie cd -[num]gewohnt laden, können Sie sie aber auch zum Zurückverfolgen Ihres Änderungsverzeichnisverlaufs ausführen.

Der primäre Mechanismus der Funktion ist sie cdselbst - und die ${OLD,}PWDUmgebungsvariablen. POSIX gibt an, dass cddiese bei jeder Pfadverschiebung geändert werden. Dabei werden nur die in der Shell integrierten Variablen verwendet und die Werte so lange gespeichert, wie Sie möchten.

mikeserv
quelle
@datUser - ich wusste, dass jemand ein dat hatte. Gern geschehen
mikeserv
4

Das Skript acd_func.sh macht genau das, was Sie beschreiben. Im Wesentlichen wird die cdFunktion überlastet und Sie können eingeben cd --, um eine Liste der zuvor besuchten Verzeichnisse abzurufen, aus denen Sie nach Nummer auswählen können. Ich finde es sehr schwierig, Bash ohne dieses zu verwenden, und es ist das erste, was ich auf einem neuen System installiere.

Nick Edwards
quelle
3

Andere behandelten bereits einige interessante Lösungen. Vor einiger Zeit habe ich meine eigene Lösung für ein verwandtes Problem entwickelt, das schnell geändert werden kann, um "Straight History" zu erstellen. Grundsätzlich wollte ich ein paar häufig verwendete Verzeichnisse "beschriften" und wollte, dass alle offenen Shells sie sehen und zwischen den Neustarts beibehalten.

#dir_labels
#functions to load and retrieve list of dir aliases

function goto_complete {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    local cur possib
    cur="${COMP_WORDS[COMP_CWORD]}"
    possib="${!dir_labels[@]}"
    COMPREPLY=( $(compgen -W "${possib}" -- ${cur}) )
}

complete -F goto_complete goto

function goto {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    key="$1"
    else
    key=default
    fi
    target="${dir_labels[$key]}"
    if [ -d "$target" ]; then
    cd "$target"
    echo "goto $key: '$target'"
    else
    echo "directory '$target' does not exist"
    fi
}

function label {
    unset dir_labels
    declare -A dir_labels
    {
    while read line; do
        ll_pre="${line%% *}"
        ll_dir="${line#* }"
        dir_labels["$ll_pre"]="$ll_dir"
    done
    } < ~/.dir_labels
    unset ll_pre
    unset ll_dir

    if [ $# -gt 0 ]; then
    target="$1"
    else
    target="default"
    fi
    dir_labels["$target"]=$PWD
    for i in "${!dir_labels[@]}"; do
    echo "$i ${dir_labels[$i]}"
    done > ~/.dir_labels
}

Grundsätzlich würde ich einfach label foodas aktuelle Verzeichnis aufrufen foo, und dann von welcher Shell auch immer, goto foowas cddirekt dort wäre. Leeres Argument: labelErstellt ein Standardziel für goto.

Ich habe mich nicht darum gekümmert, das automatische Entfernen von Aliasen zu implementieren, aber ansonsten verwende ich dies immer noch in leicht modifizierter Form.

orion
quelle
2

Sie können meine "cd history" -Funktion unter http://fex.belwue.de/fstools/bash.html verwenden

Es merkt sich jedes Verzeichnis, in dem Sie waren und mit "cdh" sehen Sie eine Liste der letzten 9 Verzeichnisse. Geben Sie einfach die Nummer ein und Sie sind wieder in diesem Verzeichnis.

Beispiel:

framstag @ wupp: /: cdh
1: / usr / local / bin
2: / var
3: /
4: / tmp / 135_pana / 1280
5: / tmp / 135_pana
6: / tmp / weihnachtsfeier
7: / tmp
8: / local / home / framstag
auswählen: 4
framstag @ wupp: / tmp / 135_pana / 1280:

cdh funktioniert mit autocd aka "cd without cd": Sie müssen weder cd noch pushd eingeben.

Framstag
quelle
2

Ich möchte Ihnen meine erweiterte CD-Funktion empfehlen:

https://github.com/dczhu/ltcd

Bildbeschreibung hier eingeben

Es bietet die folgenden Funktionen, um das Leben zu erleichtern:

  • Globale Verzeichnisliste, in der kürzlich besuchte Verzeichnisse aus allen Terminalregistern / -fenstern angezeigt werden.
  • Lokale Verzeichnisliste, die für die aktuelle Shell-Sitzung lokal ist.
  • Beide Listen unterstützen die schnelle Navigation mithilfe von j / k (runter / rauf), Zahlen und Wortsuche.
  • Globales Freispringen (zB "cd dir" oder "cd ar", um nach / path / to / foo / bar / directory / zu gehen).
treulz
quelle
Hm, sieht vielversprechend aus. Ich werde das überprüfen.
ddnomad
1

für bash im grunde: anstatt cd zu verwenden, um verzeichnisse pushdzu wechseln, werden sie gespeichert (dh gestapelt)

pushd /home; pushd /var; pushd log

Um den Stack zu sehen, benutzen Sie dirsund zur einfacheren Navigation (um die Nummern der "Stack-Einträge" zu erhalten, benutzen Sie:

dirs -v

Ausgabe:

me@myhost:/home$ dirs -v
 0  /home
 1  /var
 2  /tmp

Verwenden Sie nun diese Zahlen mit cdund ~wie:

cd ~1

Aber jetzt sind diese Nummern neu angeordnet und Position "0" ändert sich, so dass nur pushddas Verzeichnis zweimal an die oberste Position (oder verwenden Sie einen Dummy auf Position 0) wie folgt :

me@myhost:/home$ dirs -v
 0  /home
 1  /home
 2  /var
 3  /tmp

jetzt wird 1..3 dort stehen bleiben. Ich habe das irgendwo gelesen, weiß es aber nicht mehr

(um das aktuelle Verzeichnis vom Stack zu entfernen / aus dem Verlauf zu löschen popd)

eli
quelle
1

Siehe die cdh-Funktion in "Shell-Programmierung, 4e" auf Seite 349. Sie speichert den Verlauf in einem Array.

Hier ist eine erweiterte Version: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Es speichert den Verlauf in der Datei CDHISTFILE und ermöglicht das Wechseln in das neueste Verzeichnis, das eine Zeichenfolge enthält, z.

cd -src

Es installiert sich über den vorhandenen Befehl cd, indem es ein alias cd=_cd

user2251295
quelle
1

Ich wollte nur fzf-Marken als mögliche Lösung hinzufügen .

Einmal installiert, gibt es Ihnen die Befehle Markieren und Springen , um mit Lesezeichen versehene Verzeichnisse hinzuzufügen und zu suchen (ja, das ist nicht genau der vollständige Verlauf, nur die, die Sie selbst mit Lesezeichen versehen haben).

Das Problem, das ich mit pushd / popd it habe, ist das sitzungsspezifische Verhalten, dh ich möchte den gleichen Stack in einer anderen Bash-Sitzung haben oder so, was für FZF-Marken möglich ist.

Sebastian Müller
quelle
0

Ich habe die Antwort von @mikeserv ausprobiert, aber es hat bei mir nicht ganz funktioniert. Ich konnte nicht herausfinden, wie ich das Problem beheben kann, und schrieb einfach meine eigenen:

cd() {
    # Set the current directory to the 0th history item
    cd_history[0]=$PWD
    if [[ $1 == -h ]]; then
        for i in ${!cd_history[@]}; do
            echo $i: "${cd_history[$i]}"
        done
        return
    elif [[ $1 =~ ^-[0-9]+ ]]; then
        builtin cd "${cd_history[${1//-}]}" || # Remove the argument's dash
        return 
    else
        builtin cd "$@" || return # Bail if cd fails
    fi
    # cd_history = ["", $OLDPWD, cd_history[1:]]
    cd_history=("" "$OLDPWD" "${cd_history[@]:1:${#cd_history[@]}}")
}

Dies ist auch als GitHub Gist verfügbar . Um dies zu nutzen, fügen Sie einfach die Funktion in Ihre .bashrcoder ähnlich, und Sie werden in der Lage sein , die Dinge zu tun , wie cd -5zum 5 zurück th letzten Verzeichnis , das Sie in sind. cd -hGibt Ihnen einen Überblick über Ihre Geschichte.

Saagarjha
quelle