Bash CD aż do określonego folderu

16

Dużo pracuję w Magento, podobnie jak wielu ludzi, z którymi pracuję, a pisanie:

Płyta CD ../../../../../../

Aby się dowiedzieć, wciąż masz kilka katalogów z głównego katalogu „httpdocs”, dlatego próbuję utworzyć skrypt, który będzie działał zgodnie z tym pseudo-kodem:

while lowest level directory != httpdocs
    cd ../
end while;

Wydaje się to dość proste, zakładam, że musiałbym zrobić jakąś formę grep, sprawdzając, czy ostatnia część bieżącego katalogu roboczego to httpdocs, jeśli nie, po prostu przechodź o jeden poziom wyżej, aż to prawda.

Przyglądałem się temu nauce basha, choć wydaje się, że musi być już coś podobnego, a składnia mnie zastanawia.

użytkownik652650
źródło

Odpowiedzi:

8

Musi to być funkcja powłoki , a nie skrypt, ponieważ skrypt wykonuje się w nowej powłoce (a zatem nie może zmienić katalogu oryginalnej powłoki).

function cdroot()
{
  while [[ $PWD != '/' && ${PWD##*/} != 'httpdocs' ]]; do cd ..; done
}

Możesz oczywiście nazwać tę funkcję, jak chcesz.

Kilka wyjaśnień: pierwszy test ( $PWD != '/') jest zabezpieczony przed cdrootawarią na wypadek, gdybyś nie znalazł się w folderze httpdocs. Zatrzyma się, gdy dojdziesz do korzenia.

Drugi test ( ${PWD##*/} != 'httpdocs') jest nieco bardziej skomplikowany. $PWDjest zmienną zawierającą ścieżkę bieżącego katalogu. ${PWD##*/}przycina wszystko do ostatniego slashu włącznie.

cjm
źródło
Minusem tego iteracyjnego jest to, że tracisz zdolność do zrobienia cd -czegoś, aby wrócić do miejsca, w którym byłeś.
Ezequiel Muns
27

Mam funkcję wywoływaną uptow moim .bashrc, która pozwala przejść do dowolnego katalogu na bieżącej ścieżce według nazwy:

upto ()
{
    if [ -z "$1" ]; then
        return
    fi
    local upto=$1
    cd "${PWD/\/$upto\/*//$upto}"
}

Mam również uzupełnienie tej funkcji, dzięki czemu mogę uzyskać prawidłowe nazwy katalogów i uzupełnienie po naciśnięciu klawisza Tab:

_upto()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local d=${PWD//\//\ }
    COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto

Ponadto mam inną funkcję, jdktóra pozwala mi przejść do dowolnego katalogu poniżej bieżącego:

jd(){
    if [ -z "$1" ]; then
        echo "Usage: jd [directory]";
        return 1
    else
        cd **"/$1"
    fi
}

Przykład:

[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat       hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ 
dogbane
źródło
Możesz także dodać alias dla upto httpdocs.
cjm
@drogbane: jdnie wydaje się działać w każdym przypadku, czy mógłbyś wyjaśnić, jak to działa?
Cesar
@Cesar używa globstar ( **). Aby włączyć tę funkcję w powłoce bash, użyj shopt -s globstar.
dogbane
2
Jest to tak genialnie zrobione, że chciałbym dwukrotnie głosować.
droope
1
Włączyłemjd funkcję dynamicznego wykrywania i aktywacji shopt , patrz gist.github.com/Rob--W/5888648 . Testowałem go tylko z Bash 4.2.45, więc YMMV.
Rob W
5

Najprostsza funkcja bash, którą możesz włożyć do swojej .bashrc, o której mogę pomyśleć (prosta, ponieważ nie używa pętli ani procesów zewnętrznych):

cdup() {
    cd "${PWD/\/httpdocs\/*//httpdocs}"
}

Używa to rozszerzenia parametru podstawiania Wzorca, aby zastąpić wszystko po /httpdocs/w $PWD`/ httpdocs '. Wygląda to bardzo niechlujnie, ponieważ musimy uciec przed ukośnikami na ścieżce, aby odróżnić je od ukośników w składni rozszerzenia bash. Plus nie unikaj ukośników w zastępującym ciągu, więc wygląda również niespójnie.

Jeśli nie ma /httpdocs/w bieżącej ścieżce, nie zostaną wykonane żadne podstawienia i zmieni się tylko w bieżący katalog.

Na przykład, podstawienie zastąpi /a/b/c/httpdocs/e/f/gz /a/b/c/httpdocsi cddo tego katalogu.

Funkcja musi znajdować się w bieżącym środowisku powłoki (jako funkcja lub alias), ponieważ proces potomny nie może zmienić bieżącego katalogu swojego rodzica. Dlatego mówię, aby umieścić go w swoim, .bashrca nie w skrypcie powłoki.

camh
źródło
Nawiasem mówiąc, warto wspomnieć, że zabierze Cię to jak najwyżej w hierarchii (co jest prawdopodobnie najbardziej użytecznym przypadkiem użycia).
Ibrahim
3

Możesz również umieścić coś takiego w swoim profilu:

alias cdh='cd $(echo $PWD | sed -e "s/\(.*\/httpdocs\)\/.*/\1/")'

Już samo wpisanie cdhprzeniesie Cię do najwyższego httpdocskatalogu w twojej bieżącej ścieżce.

Mata
źródło
2

Nie rozwiązuje to całkowicie twojego problemu, ale zaoszczędzi cd ../../../../../../trochę. Pożyczyłem to od posta użytkownika nieznanego tutaj .


w górę N.

przeskocz N katalogów w górę w drzewie katalogów

Zamiast pisać

cd ../../../..

po prostu piszesz

up 4

i a

cd -    

przywiezie cię z powrotem

Umieść tę funkcję w pliku .bashrc, aby z niej skorzystać.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
boehj
źródło