Sistem yönetimi için birden fazla dizin arasında geçiş yapmanın hızlı bir komut satırı yolu nedir?


46

Sistem yönetimi için birden fazla dizin arasında geçiş yapmanın hızlı bir komut satırı yolu nedir? Demek istediğim, kullanabilirim pushd .ve popdgeçiş yapabilirim, ama ya katları saklamak ve yığının altından kalıcı olarak çıkarmak yerine, aralarında dolaşmak istersem?


$CDPATHbelki?
roaima

6
oh my - Ben sadece cd -bu soru başlattı googling sonra öğrendim .
Nacht - Monica'yı

@Nacht: Dosya yapısını daha önce nasıl gezdiniz?
loneboat

1
cdHer yerde el ile yaptım . Acı vericiydi. Yine de, sekme tuşuyla otomatik tamamlama kullanılır.
Volomike

1
Belki Za denemek istersiniz . Aynı çift kir içinde çok zıpladığınızda son derece kullanışlı.
Rolf,

Yanıtlar:


28

Kullanım pushdve dizin yığınında dizinler için daha sonra özel isimler: ~1,~2 vb

Örnek:

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 $ 

Bu şekilde kullanmanın en etkili yolu pushd, dizin listenizi yüklemektir, ardından geçerli dizininiz için bir dizin daha ekleyiniz ve sonra dizininizin konumunu etkilemeden durağan sayılar arasında geçiş yapabilirsiniz.


Ayrıca unutmamak gerekir cd -önceden bulunduğunuz dizine götürür. Yani olacak cd ~-.

Avantajı ~-üzerinde sadece -olmasıdır -özgüdür cdoysa ~-genişletilir sizin kabuk tarafından aynı şekilde ~1, ~2olduğu gibi. Çok uzun dizin yolları arasında bir dosyayı kopyalarken bu kullanışlı olur; Örneğin:

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

Yukarıdaki eşdeğerdir:

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

1
Ayrıca kullanabilirsinizcd -
Volomike

cd -Bir Forth gibi davranır DROP DUP, örneğin, dizin halinde bir başlar a yığını ile ABCD , bir cd -yığını değiştirir bbcd . Belki de bu bir bashhatadır, çünkü bir saniye cd -yığını abcd olarak değiştirir . Bundan cd -, yığını değiştirmenin yanı sıra önceki dizini saklamak için ayrı bir veri yapısı kullanan çıkarımda bulunabiliriz .
agc

3
@ agc, cd -kullanır $OLDPWDve başka hiçbir şey.
Joker,

Belki cd -de ilk bash özelliğiydi, daha sonra bir yığın eklediler, ancak eski kodu kırmaktan daha basit bir tasarım istediklerinden daha fazla korkuyorlardı. Önceki için düzeltme, cd -bir Forth gibi bir şey davranan OLDPWD @ SWAP OLDPWD ! DUP . aksine cd foo, cd -baskılar takas-in dizinin adı.
agc

Veya her zaman interaktif pushd sarıcı vardır (bu sorunun diğer cevapları otomatik atlama vb. İçerir).
İşe yaramaz

42

bash'yerleşik s pushdile +ve -dizin yığını dönebilecek amaç. Sözdizimi belki de kafa karıştırıcı olabilir, çünkü bu yığın sıfır tabanlı bir dizidir. Bu basit sarmalayıcı işlevleri dizin yığını içinde döner:

# 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: dört dizinden oluşan bir yığın ayarlayın.

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

Şimdi / tmp mevcut dizin ve yığın şöyle gözüküyor:

/tmp /bin /etc /home

Bir sonraki dizine yığın halinde (ve göster), dört kez değiştirin:

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

Çıktı:

/bin
/etc
/home
/tmp

Önceki dizine yığında (ve göster), dört kez değiştirin:

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

Çıktı:

/home
/etc
/bin
/tmp

Üzerine bir not cd -: Wildcard'ın cevabı $ DIRSTACK dizisinin ( $ OLDPW değişkenini kullanır) nasıl cd -kullanılmadığını göstermeye yardımcı oldu , bu da yığın tabanlı bir takasın $ DIRSTACK özelliğini etkilememesini sağladı . Bunu düzeltmek için işte size basit bir $ DIRSTACK tabanlı takas işlevi:cd -

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

Ölçek:

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

Çıktı:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp

Benim hayal kırıklığım, eşyaları yığına koymak ve yığını temizlemeyi seçinceye kadar onları orada tutmak istiyorum. Bu şekilde, itebilir, itebilir, itebilir, ardından gerektiğinde üç direkten her birinde dolaşabilirim. Örneğin, sanki tarayıcı sekmeleri gibiymişim gibi üç dizin arasında geçiş yapmam ve bir sekmeyi kapatana kadar ileri ve geri gitmem gerekiyor. Bu, komut satırına göre mi gider?
Volomike

5
Evet, inanıyorum, deneyin. Üst öğeyi çıkarmak, yapmak popd, kir değiştirmeksizin kaldırmak için yapın popd -n. Yığını temizlemek için yapın dirs -c. Ne yazık ki, bash tasarımcıları bu tür faydalı işlevleri sezgisel olmayan sözdizimine gömdüler. Bkz man bashaltında pushd, dirsvb
agc

Eserleri! Ve dokümanlardaki çamur kadar açıktı. Ben basitliği seviyorum, şimdi tekniği biliyorum.
Volomike

13

Fasd kurmanızı öneririm . Size adının sadece küçük bir kısmını yazarak zaten bulunduğunuz herhangi bir dizine hızlıca atlamanızı sağlar.

Örnek: Eğer ziyaret /home/someName/scripts/ettiyseniz, o zaman sadece z scrörneğin yazarak oraya atlayabilirsiniz . Geçmiş yığındaki sırasını veya benzeri şeyleri hatırlamak çok daha uygun.


10

Bir cdyerde, Bash eski çalışma dizininde bir ortam değişkeni saklar $OLDPWD.

cd -Eşdeğeri olan dizine geri dönebilirsiniz cd "$OLDPWD".

Bu gibi dizinler arasında ileri geri sıçrayabilirsiniz:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$

6

Bunu xyzzyyapmak için bir komut dosyası yazdım :

#!/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

Bunu kullanmamın yolu, /usr/binklasöre ve daha sonra chmod a+xüzerine kopyalamak . Daha sonra, ~/.bashrcbu satırları en altta olacak şekilde kök ve kullanıcı hesap dosyamı düzenlerim :

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

'Xy', daha hızlı yazmak için komutun kısaltılmış şeklidir.

Ardından, geçerli dizini listede ...

xyzzy this

... ve gerektiği kadar tekrarlayın. Bu listeyi ihtiyaç duyduğum dizinlerle doldurduktan sonra, bilgisayarı yeniden başlatana kadar orada kalıyorlar çünkü / tmp tekrar temizlendi. Sonra yazabilirim ...

xyzzy show

... o anda kaydedilmiş dizinleri listelemek için. Bir dizine geçmek için iki seçeneğim var. Bir seçenek, yolu dizinine göre (ve 1 tabanlı bir dizindir) şöyle belirtmektir:

xyzzy 2

... listedeki ikinci öğe olan dizine geçer. Ya da indeks numarasını bırakıp şunu yapabilirim:

xyzzy

... ihtiyacım olan her dizinde dolaşmak için. Yapabileceğiniz diğer komutlar için şunu yazın:

xyzzy help

Tabii ki, iş eklediğim aptalca yankı ifadeleri ile daha eğlenceli.

Xyzzy'nin , xyzzy yazmanın oyunda iki oda arasında geçiş yapmanıza izin vereceği Collosal Cave metin macerasına bir referans olduğunu unutmayın.


2
+1 Bununla oynamaya başladım. Güzel, ancak henüz bir dizin eklenmemişse ve sadece xyzzy yazarsanız başarısız görünüyor. Cyclenext () içindeki MAXLINES -eq 0 için bir test daha gerekir.
Joe

5

Tam olarak istediğiniz şeyi yapmasa da, z [link] adlı küçük bir senaryo da ilginizi çekebilir.

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.

Belki bir şey özledim, ama z betiğini nerede bulabilirim?
Joe

Maalesef, bağlantı z üzerindeydi. Görmeyi kolaylaştırmak için düzenleme yapacak.
Graipher

5

Orada da cd_functemelde var Petar Marinov dan cd10 girişlere up öyküsü olan: 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

Siimply kullanım cd --10 dizinlere geçmiş up listesini göstermek için cdiçin ed ve cd -N( Noraya gitmek giriş endeksidir).


4

Ben çoğunlukla ZSH'yi oh-my-zsh profiliyle kullanıyorum. Bir terminale aşağıdaki eşleşmeyi yazabilirsiniz:

# cd /ho

Ardından, sadece yukarıdaki karakterlerle başlayan girişleri gösteren tüm kabuk geçmişine gitmek için basitçe okları (yukarı ve aşağı) kullanabilirsiniz. Yani, örneğin, eğer gitti /home/morfik/Desktop/ve /home/morfik/something/çok hızlı dizinleri arasında geçiş yapabilirsiniz. Kabuk geçmişinde kaç tane giriş yaptığınız önemli değildir, ancak çok şeyiniz olduğunda, daha iyi bir ifade kullanın, yani cd /home/morfve burada klavyenizdeki yukarı / aşağı oklarına basın.

Çözüme ulaşmanın başka bir yolu var. Bu durumda tmux ve FZF kullanmanız gerekir . Sonra bir kısayol tuşu, örneğin ctrl-r yaparsınız ve bastığınızda, geçerli pencereniz bölünür ve şunu görürsünüz:

görüntü tanımını buraya girin

Şimdi listeyi aramak için ifadeleri kullanabilirsiniz. Sadece yazdım ^cd /media, bu sadece cümle ile başlayan girişleri döndürür. Tabii ki, sadece 'cd 'homekomutu ve ayrıca tüm dizin adını (sadece yol değil, sadece isim) eşleştirmek için yazabilirsiniz :

görüntü tanımını buraya girin


4

Bunu, bir grup takma adla elde edebilirsiniz. ~/.bashrc (veya eşdeğeri)

Asıl amaç, d5havuzdaki dizinler arasında geçiş yapmak için minimum tip yazmaktır (örn . Havuzdaki dizin numarası 5'e atlar). Ayrıca havuza dizin eklemek / kaldırmak çok kolaydır:

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

Artık yığında bir dizine her basışta, 0 (geçerli dir) konumundaki numaralı havuza eklenir ve çok az yazarak ( d<N>) kullanarak etrafa atlayabilir (dizinleri değiştirebilir). sadece yazarak zamanı d.

Bu takma adları kullanmanın birkaç örneği:

Numaralandırılmış dizin havuzunu görüntüleyin (geçerli dizin # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Dirs arasında geçiş: kullanın d<N>

$ d2
$ pwd
/usr

Havuza yeni bir dizin ekleyin

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

Biraz daha atla:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

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

Üstteki (geçerli) dizini havuzdan çıkarın / kaldırın

$ po
$ d
 0  /
 1  /var/log
 2  /usr

2

Eğer iselect yüklüyse, şöyle bir şey yapabilirsin:

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

Bu, size bir dizin seçmek için tam ekran bir ncurses tabanlı etkileşimli ok tuşu ile gezinilebilir bir menü cdsağlayacaktır.

Eğer kullanmadıysanız pushdgeçerli kabuk oturumda, menüde dizinleri liste sadece bir girişi, geçerli dizinde ile başlar. Yalnızca bir giriş varsa, bu dirselecttakma ad sadece cdmenü ekranı olmadan girecektir, bu nedenle etkili bir şey yapmaz ( cd -yararlı bir şey yapmasını engelleme hariç )

Listeye yeni bir dizin eklemek için, pushd dir(veya kullanmadan pushd -n dirbir dircd aynı anda ) kullanın.

Sen önceden doldurabilirsiniz pushdGözlerinde farklı aşağıdaki gibi bir şey yaparak yığını .bashrcya ~/.bash_profile:

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

Girişleri popdveya ile kaldırabilirsiniz popd -n.

Bkz help pushd, help popdve help dirsdaha fazla bilgi için bash. Ve elbette man iselect.

BTW, iselectmuhtemelen dağıtımınız için önceden paketlenmiştir. Debian ve Ubuntu vb. Ve muhtemelen diğerleri içindir.


2

5 veya 10 dizininiz varsa, çok kullanırsınız ve son zamanlarda kullandığınız 5 veya 10 dizine önem vermeniz gerekmiyorsa ,

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

Ve böylece Apache ana sayfa dizinine gitmek istediğimde sembolik bir link için Eşdeğer Takma Ad yazarken cdwyanıtladığım gibi yazdım. .


2

Çalışma dizinini hızlıca değiştirmek için atlama kullanıyorum .

Geçerli dizini eklemek için:

jump -a [bookmark-name]

Tüm yer imlerinizi listelemek için:

jump -l

Örneğin:

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

Şimdi kolayca başka bir dizine atlayabilirsiniz:

jump reports

Bash ve zsh için otomatik tamamlamayı destekler.


Düzenleme (@Joe'ye cevap olarak): ikili dosyada jump-bindepolanır /usr/local/binve bash bütünleştirme komut dosyasıyla (bilgisayarımda bulunan /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver), jumpçağıran bir bash işlevi oluşturur jump-bin.


Jump komutu nerede yaşıyor? Bende yok ve nereden alacağımı hemen göremiyorum.
Joe

2

Kullandığım aliasgezinmek için. Sık erişilen birkaç dizininiz varsa, sadece takma isimleri ayarlayın. Örneğin,

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

O zaman basitçe

e 

seni alacağım /etc.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.