Önceki / sonraki kardeş dizinine nasıl cd atabilirim?


10

Genellikle böyle bir proje dizini düzenim var

project
`-- component-a
|   `-- files...
`-- component-b
|   `-- files...
`-- component-c
    `-- files...

Genellikle componentdizinlerden birinde çalışacağım , çünkü dosyalar burada. Daha sonra kabuğa geri döndüğümde, genellikle her bileşene yazılabilir olmayan birkaç değişiklik yapmam gerektiğinde, genellikle bir kardeş dizinine geçmem gerekir. Bu durumlarda, üzerinde çalışacağım önceki kardeş dizininin veya bir sonraki kardeş dizinin ne olduğu umurumda bile değil.

Bir komutu tanımlayabilir miyim prevyoksa nextbu sadece bir cdönceki dizine mi yoksa bir sonraki dizine mi (alfabe ya da her neyse)? Çünkü cd ../com<TAB><Arrow keys>her zaman yazmak biraz yaşlanıyor.

Yanıtlar:


8

Commandlinefu çözümünü diğer yanıttan kullanmayın : güvensiz VE verimsizdir .² Bunun yerine bash, sadece aşağıdaki işlevleri kullanın. Onları ısrarcı hale getirmek için onları senin yerine koy .bashrc. Glob düzenini kullandığımı çünkü yerleşik ve kolay olduğunu unutmayın. Genellikle glob düzeni çoğu yerde alfabetiktir. Bir sonraki veya bir önceki dizin yoksa bir hata mesajı alırsınız. Özellikle, kök dizinde nextveya prevdizinini denerseniz hatayı görürsünüz /.

## bash and zsh only!
# functions to cd to the next or previous sibling directory, in glob order

prev () {
    # default to current directory if no previous
    local prevdir="./"
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No previous directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ ${x#../} == ${cwd}/ ]]; then
            # found cwd
            if [[ $prevdir == ./ ]]; then
                echo 'No previous directory.' >&2
                return 1
            fi
            cd "$prevdir"
            return
        fi
        if [[ -d $x ]]; then
            prevdir=$x
        fi
    done
    # Should never get here.
    echo 'Directory not changed.' >&2
    return 1
}

next () {
    local foundcwd=
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No next directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ -n $foundcwd ]]; then
            if [[ -d $x ]]; then
                cd "$x"
                return
            fi
        elif [[ ${x#../} == ${cwd}/ ]]; then
            foundcwd=1
        fi
    done
    echo 'No next directory.' >&2
    return 1
}

Possible Tüm olası dizin adlarını işlemez. Çıkışı ayrıştırma lsasla güvenli değildir .

² cdmuhtemelen son derece verimli olmak zorunda değildir, ancak 6 işlem biraz fazladır.


1
Aslında zsh kullanıyorum, ancak bir sonraki işlevin for-loop'undaki ilk testi değiştirirseniz, [[ -n $foundcwd ]]cevabınız bash ve zsh altında eşit derecede iyi çalışır. Çok güzel ve bunu yazdığınız için teşekkürler.
Esteis

4

Aşağıdaki işlev, kardeş dizinlerini değiştirmeye izin verir (bash işlevi)

function sib() {
    ## sib  search sibling directories 
    ##   prompt for choice (when two or more directories are found, current dir is removed from choices) 
    ##   change to directory after selection 
    local substr=$1
    local curdir=$(pwd)
    local choices=$(find .. -maxdepth 1 -type d -name "*${substr}*" | grep -vE '^..$' | sed -e 's:../::' | grep -vE "^${curdir##*/}$" | sort)
    if [ -z "$choices" ]; then
        echo "Sibling directory not found!"
        return
    fi
    local count=$(echo "$choices" | wc -l)
    if [[ $count -eq 1 ]]; then
        cd ../$choices
        return 
    fi
    select dir in $choices; do
        if [ -n "$dir" ]; then
            cd ../$dir
        fi
        break
    done
}

Kullanım örneği:

$ tree
  .
  ├── component-aaa-01
  ├── component-aaa-02
  ├── component-bbb-01
  ├── component-bbb-02
  ├── component-ccc-01
  ├── component-ccc-02
  └── component-ccc-03
  7 directories, 0 files
  $ cd component-aaa-01/
  $ sib bbb-01
  $ pwd
  component-bbb-01
  $ sib bbb
  $ pwd
  component-bbb-02
  $ sib ccc
  1) component-ccc-01
  2) component-ccc-02
  3) component-ccc-03
  #? 3
  $ pwd
  component-ccc-03
  $ sib 01
  1) component-aaa-01
  2) component-bbb-01
  3) component-ccc-01
  #? 2
  $ pwd
  component-bbb-01

Çok hoş. Jw013'ün cevabını kabul edilen cevap olarak saklıyorum, çünkü sorum ve kullanım durumum 'Bir sonraki kardeşe geçmek istiyorum ve ne dediği umurumda değil'; ama bu da yararlı ve şık, bu yüzden bir oy verin.
Esteis

2

Commandlinefu.com'da bir ipucu buldum . Ben burada nextiken bir açıklama ve eklenen bir komut ile, daha bitirilebilir hale getirmek için burada yeniden gönderiyorum .

alias prev='cd ../"$(ls -F .. | grep '/' | grep -B1 -xF "${PWD##*/}/" | head -n 1)"'
alias next='cd ../"$(ls -F .. | grep '/' | grep -A1 -xF "${PWD##*/}/" | tail -n 1)"'

Sihir $ (...) bloğunda. Birkaç komutu birbirine aşağıdaki gibi bağlar:

ls -F .. |   # list items in parent dir; `-F` requests filetype indicators
grep '/' |   # select the directories (written as  `mydir/`)
grep -B1 -xF "${PWD##*/}/" |   # search for the name of the current directory in the output;
                               # print it and the line preceding it
head -n 1    # the first of those two lines contains the name of the previous sibling

2
Bulduğunuz komutun bazı sorunları var. En berbat olanları düzeltmek için düzenledim: dizin adını bir grep deseni olarak ele alıyordu ve bir alt dizeyle eşleşmesine izin veriyordum; ve dizin adı kabuk genişleme (kelime bölme ve globbing) iki kez (: hep değişken ve komut değiştirmelerin çift tırnak kullanmak geçmesi vardı "$foo", "$(foo)"). Ayrıca , çıktısını ayrıştırmak lsgüvenilmezdir , yazdırılamayan karakterler içeren dosya adlarında başarısız olabilir.
Gilles 'SO- kötü olmayı bırak'
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.