Jak można szybko przełączać się między wieloma katalogami w celu administrowania systemem?

46

Jak można szybko przełączać się między wieloma katalogami w celu administrowania systemem? Mam na myśli, że mogę używać pushd .i popdprzełączać, ale co, jeśli chcę przechowywać wielokrotności i przełączać się między nimi, zamiast trwale wyrzucać je z dołu stosu?

Volomike
źródło
$CDPATHbyć może?
roaima
6
o mój - właśnie się dowiedziałem cd -po googlowaniu zainicjowanym z tego pytania.
Nacht - Przywróć Monikę
@Nacht: Jak nawigowałeś wcześniej w strukturze plików?
Loneboat
1
Robiłam cdwszędzie ręcznie. Było bolesne Używano jednak automatycznego uzupełniania z klawiszem Tab.
Volomike
1
Może chcesz spróbować . Niezwykle przydatny, gdy często przeskakujesz w obrębie tej samej pary katalogów.
Rolf

Odpowiedzi:

28

Zastosowanie pushda następnie specjalne nazwy katalogów w Twojej stosu katalogów: ~1, ~2, itd.

Przykład:

tmp $ dirs -v
 0  /tmp
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
tmp $ cd ~3
music $ dirs -v
 0  /tmp/music
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
music $ cd ~2
photos $ cd ~4
pictures $ cd ~3
music $ cd ~1
scripts $ 

Najskuteczniejszym sposobem użycia pushdw ten sposób jest załadowanie listy katalogów, a następnie dodanie jeszcze jednego katalogu, aby był twoim bieżącym katalogiem, a następnie możesz przeskakiwać między liczbami statycznymi bez wpływu na pozycję katalogów na stosie.


Warto również zauważyć, że cd -zabierze Cię do ostatniego katalogu jesteś w. Tak będzie cd ~-.

Przewaga ~-nad właśnie -jest to, że -jest specyficzny cd, natomiast ~-jest rozszerzana przez powłokę w ten sam sposób, że ~1, ~2itp są. Jest to przydatne przy kopiowaniu pliku między bardzo długimi ścieżkami katalogu; na przykład:

cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-

Powyższe jest równoważne z:

cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
Dzika karta
źródło
1
Można również użyćcd -
Volomike
cd -zachowuje się jak czwarty DROP DUP, np. jeśli zaczyna się od katalogu a , przy stosie abcd , a cd -zmienia stos na bbcd . Być może to bashjednak błąd, ponieważ sekunda cd -zmienia stos z powrotem na abcd . Z tego możemy wywnioskować, że cd -oprócz zmiany stosu używa innej osobnej struktury danych do przechowywania poprzedniego katalogu.
agc
3
@agc, cd -zastosowania $OLDPWDi nic więcej.
Wildcard
Być może cd -była to wcześniejsza funkcja bash , a potem dodali stos, ale bali się złamania starego kodu bardziej niż chcieli prostszego projektu. Korekta do poprzedniej, cd -działa jak Forth OLDPWD @ SWAP OLDPWD ! DUP . W przeciwieństwie do cd foo, cd -wypisuje nazwę zamienionego katalogu.
agc
Lub zawsze jest interaktywne opakowanie pushd (inne odpowiedzi na to pytanie obejmują autojump itp.).
Bezużyteczne
42

bash„s wbudowane pushdz +i -opcji można obrócić stos katalogów. Składnia może być nieco myląca, być może dlatego, że ten stos jest tablicą zerową . Te proste funkcje opakowania przełączają się między stosami katalogów:

# cd to next     directory in stack (left  rotate)
ncd(){ pushd +1 > /dev/null ; }
# cd to previous directory in stack (right rotate)
pcd(){ pushd -0 > /dev/null ; }

Test: ustaw stos czterech katalogów.

dirs -c   # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp

Teraz / tmp jest bieżącym katalogiem, a stos wygląda następująco:

/tmp /bin /etc /home

Przejdź do następnego katalogu na stosie (i pokaż go) cztery razy:

ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd

Wynik:

/bin
/etc
/home
/tmp

Przejdź do poprzedniego katalogu na stosie (i pokaż go) cztery razy:

pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd

Wynik:

/home
/etc
/bin
/tmp

Uwaga na temat cd -: Odpowiedź Wildcard pomogła zilustrować, w jaki cd -sposób nie korzysta z tablicy $ DIRSTACK (używa zmiennej $ OLDPW ), więc cd -nie wpływa to na $ DIRSTACK , tak jak powinna polegać zamiana stosów. Aby to naprawić, oto prosta funkcja wymiany w oparciu o $ DIRSTACK :

scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }

Test:

dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs

Wynik:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
agc
źródło
Moją frustracją jest to, że chcę umieścić przedmioty na stosie i trzymać je tam, dopóki nie zdecyduję się wyczyścić stosu. W ten sposób mogę pchać, pchać, pchać, a następnie cyklicznie przewijać każdy z trzech katalogów, jeśli to konieczne. Powiedzmy na przykład, że muszę przerzucać między trzema katalogami, jakby były jak zakładki przeglądarki, i iść tam iz powrotem, dopóki nie zamknę karty. Czy rozwiązuje to w sposób wiersza poleceń?
Volomike
5
Tak, wierzę, że tak, spróbuj. Aby usunąć najwyższy element, wykonaj popd, aby usunąć go bez zmiany katalogów, wykonaj popd -n. Aby wyczyścić stos, wykonaj dirs -c. Szkoda, że projektanci bash zakopali takie przydatne funkcje w nieintuicyjnej składni. Zobacz man bashponiżej pushd, dirsitp
AGC
Pracuje! I było jasne jak błoto w dokumentach. Podoba mi się jego prostota, teraz, kiedy znam technikę.
Volomike
13

Sugeruję zainstalowanie fasd . Daje to możliwość szybkiego przejścia do dowolnego katalogu, w którym już byłeś, wpisując tylko niewielką część jego nazwy.

Przykład: jeśli odwiedziłeś /home/someName/scripts/, możesz tam wskoczyć, pisząc z scrna przykład. Jest to o wiele wygodniejsze niż zapamiętywanie kolejności w stosie historii lub czegoś podobnego.

kaqqao
źródło
10

Kiedy cdgdzieś Bash przechowuje stary katalog pracujących zmienną środowiskową, $OLDPWD.

Możesz wrócić do tego katalogu za pomocą cd -, co jest równoważne z cd "$OLDPWD".

Możesz podskakiwać między katalogami w następujący sposób:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$
RJHunter
źródło
6

Napisałem skrypt o xyzzytej nazwie :

#!/bin/bash

i="$1"
i=$((${i//[^0-9]/}))
i="$(($i-1+0))"

b="$2"
b=$((${b//[^0-9]/}))
b="$(($b-1+0))"

if [ -z "$XYZZY_INDEX" ]; then
    XYZZY_INDEX="$((-1))"
fi

if [ ! -f "/tmp/xyzzy.list" ]; then
    touch /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
fi
readarray -t MYLIST < /tmp/xyzzy.list

showHelp(){
read -r -d '' MYHELP <<'EOB'
xyzzy 1.0

A command for manipulating escape routes from grues. Otherwise known as a useful system admin
tool for storing current directories and cycling through them rapidly. You'll wonder why this
wasn't created many moons ago.

Usage: xyzzy [options]

help/-h/--help      Show the help.

this/-t/--this      Store the current directory in /tmp/xyzzy.list

begone/-b/--begone  Clear the /tmp/xyzzy.list file. However, succeed with a number and
            it clears just that item from the stored list.

show/-s/--show      Show the list of stored directories from /tmp/xyzzy.list

. #         Use a number to 'cd' to that directory item in the stored list. This syntax is odd:

            . xyzzy 2

            ...would change to the second directory in the list

. [no options]      Use the command alone and it cd cycles through the next item in the stored 
            list, repeating to the top when it gets to the bottom. The dot and space before xyzzy
            is required in order for the command to run in the current shell and not a subshell:

            . xyzzy

Note that you can avoid the odd dot syntax by adding this to your ~/.bashrc file:

  alias xyzzy=". xyzzy"

and then you can do "xyzzy" to cycle through directories, or "xyzzy {number}" to go to a
specific one.

May you never encounter another grue.

Copyright (c) 2016, Mike McKee <https://github.com/volomike>
EOB
    echo -e "$MYHELP\n"
}

storeThis(){
    echo -e "With a stroke of your wand, you magically created the new escape route: $PWD"
    echo "$PWD" >> /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
}

begoneList(){
    if [[ "$b" == "-1" ]]; then
        echo "POOF! Your escape routes are gone. We bless your soul from the ever-present grues!"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
    else
        echo -n "Waving your wand in the dark, you successfully manage to remove one of your escape routes: "
        echo "${MYLIST[${b}]}"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
        for x in "${MYLIST[@]}"; do
            if [[ ! "$x" == "${MYLIST[${b}]}" ]]; then
                echo "$x" >> /tmp/xyzzy.list
            fi
        done
    fi
}

showList(){
    echo -e "These are your escape routes:\n"
    cat /tmp/xyzzy.list
}

cycleNext(){
    MAXLINES=${#MYLIST[@]}
    XYZZY_INDEX=$((XYZZY_INDEX+1))
    if [[ $XYZZY_INDEX > $(($MAXLINES - 1)) ]]; then
        XYZZY_INDEX=0
    fi
    MYLINE="${MYLIST[${XYZZY_INDEX}]}"
    cd "$MYLINE";
}

switchDir(){
    MYLINE="${MYLIST[${i}]}"
    cd "$MYLINE";
}

if [[ "$@" == "" ]];
then
    cycleNext
fi;

while [[ "$@" > 0 ]]; do case $1 in
    help) showHelp;;
    --help) showHelp;;
    -h) showHelp;;
    show) showList;;
    -s) showList;;
    --show) showList;;
    list) showList;;
    this) storeThis;;
    --this) storeThis;;
    -t) storeThis;;
    begone) begoneList;;
    --begone) begoneList;;
    *) switchDir;;
    esac; shift
done

export XYZZY_INDEX

Używam tego, aby skopiować do /usr/binfolderu, a następnie chmod a+xna nim. Następnie edytuję ~/.bashrcplik konta root i użytkownika , aby na dole zamieścić następujące wiersze:

alias xyzzy='. xyzzy'
alias xy='. xyzzy'

„Xy” jest skróconą formą polecenia do szybszego pisania.

Następnie mogę zapisać bieżący katalog na liście za pomocą ...

xyzzy this

... i powtórz w razie potrzeby. Po wypełnieniu tej listy katalogami, których potrzebuję, pozostają tam aż do ponownego uruchomienia komputera, ponieważ wtedy / tmp zostanie ponownie wyczyszczone. Następnie mogę wpisać ...

xyzzy show

... aby wyświetlić listę aktualnie zapisanych katalogów. Aby przejść do katalogu, mam dwie możliwości. Jedną z opcji jest określenie ścieżki według indeksu (i jest to indeks oparty na 1) w następujący sposób:

xyzzy 2

... który przeszedłby do katalogu, który jest drugim elementem na liście. Lub mógłbym pominąć numer indeksu i po prostu zrobić:

xyzzy

... aby przechodził przez każdy katalog, tak jak potrzebuję. Aby uzyskać więcej poleceń, które możesz wykonać, wpisz:

xyzzy help

Oczywiście praca jest przyjemniejsza dzięki głupim wypowiedziom echa, które dodałem.

Zauważ, że xyzzy jest odniesieniem do przygody tekstowej Collosal Cave , w której wpisanie xyzzy pozwoliłoby ci przełączać się między dwoma pokojami w grze, aby uniknąć gracji.

Volomike
źródło
2
+1 Zacząłem z tym grać. To miłe, ale wydaje się, że zawodzi, jeśli nie dodano jeszcze żadnych katalogów i wprowadzasz po prostu xyzzy. Potrzebuje jeszcze jednego testu na MAXLINES -eq 0 w cyclenext ().
Joe
5

Używam małego skryptu o nazwie z [link] , który może również być interesujący, nawet jeśli nie robi dokładnie tego, o co prosiłeś.

NAME
       z - jump around

SYNOPSIS
       z [-chlrtx] [regex1 regex2 ... regexn]

AVAILABILITY
       bash, zsh

DESCRIPTION
       Tracks your most used directories, based on 'frecency'.

       After  a  short  learning  phase, z will take you to the most 'frecent'
       directory that matches ALL of the regexes given on the command line, in
       order.

       For example, z foo bar would match /foo/bar but not /bar/foo.
Graipher
źródło
Może coś przeoczyłem, ale gdzie znajdę sam skrypt Z?
Joe
Przepraszamy, link był na Z. Będzie edytować, aby ułatwić widzenie.
Graipher
5

Jest również cd_funcod Petara Marinowa, to w zasadzie cdz historią do 10 wpisów: http://linuxgazette.net/109/misc/marinov/acd_func.html

# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain

cd_func ()
{
  local x2 the_new_dir adir index
  local -i cnt

  if [[ $1 ==  "--" ]]; then
    dirs -v
    return 0
  fi

  the_new_dir=$1
  [[ -z $1 ]] && the_new_dir=$HOME

  if [[ ${the_new_dir:0:1} == '-' ]]; then
    #
    # Extract dir N from dirs
    index=${the_new_dir:1}
    [[ -z $index ]] && index=1
    adir=$(dirs +$index)
    [[ -z $adir ]] && return 1
    the_new_dir=$adir
  fi

  #
  # '~' has to be substituted by ${HOME}
  [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

  #
  # Now change to the new dir and add to the top of the stack
  pushd "${the_new_dir}" > /dev/null
  [[ $? -ne 0 ]] && return 1
  the_new_dir=$(pwd)

  #
  # Trim down everything beyond 11th entry
  popd -n +11 2>/dev/null 1>/dev/null

  #
  # Remove any other occurence of this dir, skipping the top of the stack
  for ((cnt=1; cnt <= 10; cnt++)); do
    x2=$(dirs +${cnt} 2>/dev/null)
    [[ $? -ne 0 ]] && return 0
    [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
    if [[ "${x2}" == "${the_new_dir}" ]]; then
      popd -n +$cnt 2>/dev/null 1>/dev/null
      cnt=cnt-1
    fi
  done

  return 0
}

alias cd=cd_func

if [[ $BASH_VERSION > "2.05a" ]]; then
  # ctrl+w shows the menu
  bind -x "\"\C-w\":cd_func -- ;"
fi

Wystarczy użyć, cd --aby wyświetlić listę przeszłych do 10 katalogów, do których cdedytowałeś i cd -N(gdzie Njest indeks pozycji), aby tam przejść.

phk
źródło
4

Najczęściej używam ZSH z profilem oh-my-zsh . Możesz wpisać w terminalu następujące dopasowanie:

# cd /ho

Następnie możesz po prostu użyć strzałek (w górę i w dół), aby przejść przez całą historię powłoki, która pokazuje tylko te wpisy, które zaczynają się od powyższych znaków. Na przykład, jeśli przejdziesz do /home/morfik/Desktop/i /home/morfik/something/, możesz bardzo szybko przełączać się między katalogami. Nie ma znaczenia, ile wpisów masz w historii powłoki, ale gdy masz ich dużo, po prostu użyj lepszego wyrażenia, tj. cd /home/morfI tutaj naciskaj strzałki w górę / w dół na klawiaturze.

Istnieje również inny sposób na osiągnięcie tego rozwiązania. W takim przypadku musisz użyć tmux i FZF . Następnie po prostu tworzysz skrót, na przykład ctrl-r, a gdy go naciśniesz, bieżące okno zostanie podzielone i zobaczysz:

wprowadź opis zdjęcia tutaj

Teraz możesz używać wyrażeń do przeszukiwania listy. Właśnie wpisałem ^cd /media, co zwraca tylko wpisy zaczynające się od frazy. Oczywiście możesz po prostu wpisać, 'cd 'homeaby dopasować polecenie, a także całą nazwę katalogu (nie ścieżkę, tylko nazwę):

wprowadź opis zdjęcia tutaj

Michaił Morfikow
źródło
4

Możesz to osiągnąć za pomocą kilku aliasów w swoim ~/.bashrc(lub równoważnym)

Głównym celem jest niemal minimalne wpisywanie (np. d5Skoki do katalogu nr 5 w puli), aby przełączać się między katalogami w puli. Chcemy również ułatwić dodawanie / usuwanie katalogów do / z puli:

alias pd=pushd
alias po=popd
alias d='dirs -v'
alias d0=d
alias d1='pd +1'
alias d2='pd +2'
alias d3='pd +3'
alias d4='pd +4'
alias d5='pd +5'
alias d6='pd +6'
alias d7='pd +7'
alias d8='pd +8'
alias d9='pd +9'
alias d10='pd +10'
# -- feel free to add more aliases if your typical dir pool is larger than 10

Teraz za każdym razem, gdy wypychasz katalog na stosie, zostaje on dodany do puli numerowanej w pozycji 0 (bieżący katalog) i możesz przeskakiwać (przełączać katalogi), używając bardzo małej d<N>liczby znaków ( ), i możesz przeglądać swoją numerowaną bieżącą pulę w dowolnym czas po prostu wpisując d.

Kilka przykładów użycia tych aliasów:

Wyświetl numerowaną pulę katalogów (aktualny katalog to # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Przełączaj między katalogami: użyj d<N>

$ d2
$ pwd
/usr

Dodaj nowy katalog do puli

$ pd /var/log
$ d
 0  /var/log
 1  /usr
 2  /tmp
 3  /

Przeskocz jeszcze:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

$ d
 0  /tmp
 1  /
 2  /var/log
 3  /usr

Usuń / pop górny (bieżący) katalog z puli

$ po
$ d
 0  /
 1  /var/log
 2  /usr
arielf
źródło
2

Jeśli masz zainstalowany iselect , możesz zrobić coś takiego:

$ alias dirselect='cd $(iselect -a $(dirs -l -p | sort -u))'
$ dirselect

To da Ci pełnoekranowe, oparte na ncurses, interaktywne menu nawigacyjne ze strzałkami do wyboru katalogu cddo.

Jeśli nie używałeś pushdw bieżącej sesji powłoki, lista katalogów w menu zaczyna się od jednego wpisu, twojego bieżącego katalogu. Jeśli jest tylko jeden wpis, ten dirselectalias przejdzie cddo niego bez ekranu menu, więc skutecznie nic nie robi (poza tym, że nie cd -robi nic przydatnego)

Aby dodać nowy katalog do listy, użyj pushd dir(lub pushd -n dirdodaj katalog bez cd-ing w tym samym czasie)

Można wstępnie wypełnić pushdstos wykonując coś jak poniżej w twojej .bashrclub ~/.bash_profile:

for d in /var/tmp /tmp /path/to/somewhere/interesting ; do 
  pushd -n "$d" > /dev/null
done

Możesz usunąć wpisy za pomocą popdlub popd -n.

Zobacz help pushd, help popdi help dirsw bash, aby uzyskać więcej informacji. I oczywiście man iselect.

BTW, iselectjest prawdopodobnie dostępny w paczce dla twojej dystrybucji. To jest dla Debiana i Ubuntu itp. I prawdopodobnie także dla innych.

cas
źródło
2

Jeśli masz 5 lub 10 katalogów, z których często korzystasz i niekoniecznie dbasz o ostatnio używane 5 lub 10 katalogów, skonfiguruj aliasy poleceń, takie jak

alias cdw="cd /var/www/html" 

Kiedy więc chcę przejść do katalogu strony głównej Apache, piszę po prostu, cdwgdy odpowiedziałem w ekwiwalencie aliasu dla dowiązania symbolicznego? .

Mark Stewart
źródło
2

Używam skoku, aby szybko zmienić katalog roboczy.

Aby dodać bieżący katalog:

jump -a [bookmark-name]

Aby wyświetlić listę wszystkich zakładek:

jump -l

na przykład:

------------------------------------------------------------------
 Bookmark    Path                                                 
------------------------------------------------------------------
 reports     ~/mydir/documents/reports
 projects    ~/documents/projects
 dl          ~/Downloads                     
------------------------------------------------------------------

Teraz możesz łatwo przejść do innego katalogu:

jump reports

Obsługuje autouzupełnianie dla bash i zsh.


Edycja (w odpowiedzi na @Joe): plik binarny jump-binjest przechowywany w /usr/local/bin, a wraz ze skryptem integracji bash (na moim komputerze w /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver) znajduje się funkcja bash, jumpktóra wywołuje jump-bin.

ponownie
źródło
Gdzie mieszka polecenie skoku? Nie mam tego i nie od razu widzę, skąd go wziąć.
Joe
2

Używam aliasdo nawigacji. Jeśli masz kilka często używanych katalogów, po prostu ustaw aliasy. Na przykład,

alias e='cd /etc'
alias h='cd /home'
alias al='cd /var/log/apache2/'

Więc po prostu

e 

zabierze cię do /etc.

Security Beast
źródło