Czy mamy więcej historii na cd?

Odpowiedzi:

31

Polecenie, którego szukasz, to pushdi popd.

Można zobaczyć praktyczny przykład roboczą pushdi popdod tutaj .

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
źródło
1
Są też $OLDPWDprzypadki, gdy chcesz przerzucać się między dwoma katalogami za pomocą tego samego polecenia, ale nie jestem pewien, czy jest to specyficzne dla powłoki i specyficzne dla dystrybucji / jądra.
mechalynx
4
@ivy_lynx OLDPWDistnieje we wszystkich powłokach POSIX, ale jest bezużyteczny w przypadku tego pytania, które pyta, jak wyjść poza to (pytanie już wspomina, cd -który jest skrótem cd "$OLDPWD").
Gilles „SO- przestań być zły”
2
Czy jest jakiś powód, którego używasz cd /tmp/dir1; pushd . zamiast tylko pushd /tmp/dir1?
GnP
@gnp, bez konkretnego powodu. Właśnie zostało wzięte z linku, o którym wspomniałem w odpowiedzi. pushd /tmp/dir1powinien działać dobrze.
Ramesh
1
Ok, właśnie wybrałem moją ciekawość. Chciałbym zasugerować, abyś poprawił swoją odpowiedź, podając rzeczywisty przykład, używając pushdi popddo przeglądania drzewa katalogów tam iz powrotem. Twoja odpowiedź jest już poprawna.
GnP
53

Nie określiłeś, której powłoki używasz, więc niech to będzie wymówka do reklamowania zsh.

Tak, mamy więcej historię cd, mianowicie cd -2, cd -4itd. Bardzo wygodna jest cd -TAB, zwłaszcza z systemem wykończenia i kolory włączone:

Oto, co mam w .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'

A wynik:

wprowadź opis zdjęcia tutaj

jimmij
źródło
4
bash bash bash bash
Tim
7
OK, nie usunę tej odpowiedzi, być może będą przydatne dla innych.
jimmij
23
O ile pytanie nie dotyczy konkretnie tego pytania bash, jest to prawidłowa odpowiedź. Nie usuwaj go.
liori
Co się stanie, jeśli OP zmodyfikuje swoje pytanie tak, aby zawierało tylko bash, czy ta odpowiedź będzie nadal aktualna?
Ooker
3
Warto wspomnieć, że poza tym setopt AUTO_PUSHDżadna z powyższych konfiguracji nie jest wymagana, aby uzyskać wszechobecny stos katalogów z ukończeniem w magazynie zsh. PUSHD_MINUSodwraca sens cd +i cd -(kwestia gustu), nie CDABLE_VARSma znaczenia dla stosów katalogów, a zstylepodane tutaj wywołanie po prostu dodaje kolorowanie do wyniku ukończenia stosu katalogów. Należy jednak zainicjować podsystem ukończenia za pomocą autoload -U compinit && compinit.
wjv 07.04.16
13

Aby odpowiedzieć na pytanie dotyczące „więcej historii”. Nie. cd -Funkcja w Bash obsługuje tylko jeden katalog, do którego można „przerzucić” z powrotem. Jak stwierdza @Ramesh w swojej odpowiedzi. Jeśli chcesz mieć dłuższą historię katalogów, możesz użyć pushdi popdzapisać katalog lub powrócić do poprzedniego.

Możesz także zobaczyć listę tego, co aktualnie znajduje się na stosie za pomocą dirspolecenia.

Szczegółowe wyjaśnienie można znaleźć w tej odpowiedzi zatytułowanej: Jak korzystać z poleceń pushd i popd? .

slm
źródło
Zawarłem odniesienie z twojej odpowiedzi. Mam nadzieję, że nie masz nic przeciwko. :)
Ramesh
@Ramesh - nie ma mowy.
slm
8

Możesz zainstalować i używać mojego narzędzia dirhistory do bash.

Zasadniczo jest to demon, który zbiera zmiany katalogów ze wszystkich twoich powłok, oraz program Cdk, który wyświetla historię i pozwala wybrać dowolny katalog do przełączenia (więc nie jesteś ograniczony do stosu).

cjm
źródło
7

Masz tyle historii, ile chcesz:

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

Jest to funkcja powłoki, która powinna umożliwić dowolnej powłoce kompatybilnej z POSIX oferowanie historii w zshstylu cd. Wykonuje całą swoją pracę bez wywoływania pojedynczej podpowłoki i uważam, że jego przepływ jest całkiem niezły - wydaje się, że poprawnie obsługuje wszystkie przypadki przy umiarkowanych testach.

Funkcja stara się grać z otoczeniem tak dobrze, jak to możliwe, wciąż polegając na w pełni przenośnej składni - przyjmuje tylko jedno założenie, a mianowicie, że $DIRSTACKzmienna środowiskowa jest jej własnością do zrobienia, jak chce.

Kanonizuje wszystkie ścieżki, w których się przechowuje, $DIRSTACKi serializuje je wszystkie w pojedynczych cudzysłowach - chociaż zapewnia, że ​​każda z nich jest bezpiecznie cytowana i serializowana przed dodaniem jej do wartości zmiennej i nie powinna mieć problemów z żadnymi znakami specjalnymi jakiegokolwiek rodzaju . Jeśli $DIRSTACKMAXzmienna środowiskowa jest ustawiona, użyje jej jako górnego limitu liczby ścieżek, które zachowuje w historii, w przeciwnym razie limit jest jeden.

Jeśli załadujesz funkcję tak cdjak zwykle, ale będziesz mógł również zrobić to, cd -[num]aby prześledzić historię zmian w katalogu zmian.

Podstawowym mechanizmem tej funkcji jest cdsama w sobie - i ${OLD,}PWDzmienne środowiskowe. POSIX określa, że cdzmieniają je dla każdego ruchu ścieżki - dlatego używa tylko wbudowanych zmiennych powłoki i zapisuje wartości tak długo, jak chcesz.

mikeserv
źródło
@datUser - wiedziałem, że ktoś ma dane. jesteś bardzo mile widziany
mikeserv
4

Acd_func.sh skrypt robi dokładnie to, co opisujesz. Zasadniczo przeciąża cdfunkcję i umożliwia pisanie, aby cd --uzyskać listę poprzednio odwiedzanych katalogów, z których można wybrać numer. Bez tego bardzo trudno mi używać bash, a to pierwsza rzecz, którą instaluję na nowym systemie.

Nick Edwards
źródło
3

Inne dotyczyły już kilku interesujących rozwiązań. Jakiś czas temu stworzyłem własne rozwiązanie pokrewnego problemu, które można szybko zmodyfikować, aby tworzyć „prostą historię”. Zasadniczo chciałem „opatrzyć etykietą” kilka często używanych katalogów i chciałem, aby wszystkie otwarte powłoki je widziały i aby pozostawały między restartami.

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

Zasadniczo zrobiłbym po prostu label foowywołać bieżący katalog foo, a następnie z dowolnej powłoki, co goto fooby cdtam było bezpośrednio. Pusty argument: labelutworzyłby domyślny cel dla goto.

Nie zawracałem sobie głowy wdrażaniem automatycznego usuwania aliasów, ale poza tym nadal używam tego w nieco zmodyfikowanej formie.

orion
źródło
2

Możesz użyć mojej funkcji „historii CD” ze strony http://fex.belwue.de/fstools/bash.html

Zapamiętuje każdy katalog, w którym byłeś, a wraz z „cdh” zobaczysz listę 9 ostatnich katalogów. Po prostu wpisz numer i wrócisz do tego katalogu.

Przykład:

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
wybierz: 4
framstag @ wupp: / tmp / 135_pana / 1280:

cdh działa z autocd aka „cd bez cd”: nie musisz wpisywać cd ani pushd.

Framstag
źródło
2

Chciałbym polecić Ci moją rozszerzoną funkcję „cd”:

https://github.com/dczhu/ltcd

wprowadź opis zdjęcia tutaj

Zapewnia następujące funkcje ułatwiające życie:

  • Globalna lista reż., Która pokazuje ostatnio przeglądane rewersy ze wszystkich kart / okien terminala.
  • Lokalny katalog katalogu, który jest lokalny dla bieżącej sesji powłoki.
  • Obie listy obsługują szybką nawigację za pomocą j / k (góra / dół), liczb i wyszukiwania słów.
  • Global free jumping (np. „Cd dir” lub „cd ar”, aby przejść do / path / to / foo / bar / directory /).
treulz
źródło
Hm, wygląda obiecująco. Sprawdzę to.
ddnomad
1

dla bash , w zasadzie: zamiast używać cd użyj pushddo zmiany katalogów, więc są one zapisywane (czyli ułożone w stos)

pushd /home; pushd /var; pushd log

Aby zobaczyć użycie stosu dirsi ułatwić nawigację (aby uzyskać numery „wpisów stosu”, użyj:

dirs -v

Wynik:

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

Teraz wykorzystać te numery z cdi ~jak:

cd ~1

Ale teraz te liczby są teraz przestawiane i pozycja „0” ulegnie zmianie, więc wystarczy pushddwa razy katalog do najwyższej pozycji (lub użyć manekina na pozycji 0), np .:

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

teraz 1..3 utrzyma tam pozycję Przeczytałem to gdzieś, ale już nie wiem, więc przepraszam, że nie wyraziłem uznania

(aby zwolnić bieżący katalog ze stosu / usunąć go z historii popd)

eli
źródło
1

Zobacz funkcję cdh w „Programowaniu powłoki, 4e” na stronie 312. Utrzymuje historię w tablicy.

Oto bardziej zaawansowana wersja: https://drive.google.com/open?id=0B4f-lR6inxQWQ1pPZVpUQ3FSZ2M

Przechowuje historię w pliku CDHISTFILE i umożliwia przejście do najnowszego katalogu zawierającego ciąg znaków, np.

cd -src

Instaluje się na istniejącym poleceniu cd, wykonując polecenie alias cd=_cd

użytkownik2251295
źródło
1

Chciałem tylko dodać znaki fzf jako możliwe rozwiązanie.

Po zainstalowaniu daje ci znak komend i przeskakuje, aby dodać i wyszukać katalogi z zakładkami (tak, to nie jest dokładnie pełna historia, tylko te, które sam dodałeś do zakładek).

Problem, który mam z zachowaniem specyficznym dla sesji pushd / popd it, tzn. Chciałbym mieć ten sam stos w różnych sesjach bash lub tak, co jest możliwe dla znaków fzf.

Sebastian Müller
źródło
0

Próbowałem odpowiedzi udzielonej przez @mikeserv, ale dla mnie to nie zadziałało. Nie mogłem wymyślić, jak to naprawić, więc po prostu napisałem własny:

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[@]}}")
}

Jest to również dostępne jako GitHub Gist . Aby to wykorzystać, wystarczy wkleić na swoją funkcję .bashrclub podobny, a będziesz w stanie robić rzeczy, jak cd -5wrócić do 5 th ostatni katalog Byłaś w. cd -hDaje przegląd swojej historii.

saagarjha
źródło