Bash CD fino a quando in una determinata cartella


16

Lavoro molto in Magento, così come molte persone con cui lavoro, e diventa fastidioso dover scrivere:

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

Per scoprire che sei ancora poche directory dalla cartella principale 'httpdocs', quindi sto provando a creare uno script che segue questo pseudo-codice:

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

Sembra piuttosto semplice, suppongo che dovrei fare una qualche forma di grep per verificare se l'ultima parte della directory di lavoro corrente è httpdocs, se non semplicemente continuare a salire di livello fino a quando non è vera.

Ho cercato di imparare bash per questo, anche se sembra che ci sia già qualcosa di simile già presente, e la sintassi mi confonde all'infinito.

Risposte:


8

Questa deve essere una funzione shell , non uno script, perché uno script viene eseguito in una nuova shell (e quindi non può cambiare la directory della shell originale).

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

Puoi ovviamente nominare la funzione come preferisci.

Qualche spiegazione: Il primo test ( $PWD != '/') è un fail-safe nel caso in cui lo fai cdrootquando non sei all'interno di una cartella httpdocs. Si fermerà quando arriverai alla radice.

Il secondo test ( ${PWD##*/} != 'httpdocs') è un po 'più complicato. $PWDè una variabile che contiene il percorso della directory corrente. ${PWD##*/}taglia tutto fino all'ultima barra inclusa.


Il rovescio della medaglia di questo iterativo è che perdi la tua capacità di fare solo un cd -secondo momento per tornare al punto in cui eri.
Ezequiel Muns,

27

Ho una funzione chiamata uptonel mio .bashrc che ti permette di andare in qualsiasi directory sul percorso corrente per nome:

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

Ho anche il completamento per questa funzione, in modo che mi dia nomi di directory validi e il completamento quando premo tab:

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

Inoltre, ho un'altra funzione jdche mi permette di saltare a qualsiasi directory sotto quella corrente:

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

Esempio:

[/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] $ 

Puoi anche aggiungere un alias per upto httpdocs.
cjm

@drogbane: jdnon sembra funzionare in ogni caso, ti dispiacerebbe spiegare come funziona?
Cesar,

@Cesar utilizza globstar ( **). Per abilitare questa funzione nella tua shell bash usa shopt -s globstar.
dogbane,

2
Questo è fatto così brillantemente, vorrei poter votare due volte.
droope

1
Ho incluso un rilevamento e un'attivazione dinamici dello shopt nella jdfunzione, vedere gist.github.com/Rob--W/5888648 . L'ho provato solo con Bash 4.2.45, quindi YMMV.
Rob W,

5

La più semplice funzione bash che puoi mettere nella tua a .bashrccui riesco a pensare (semplice perché non usa loop o processi esterni) è:

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

Questo utilizza il modello di sostituzione espansione di parametro per sostituire tutto dopo /httpdocs/in $PWDcon `/ httpdocs'. Sembra molto disordinato perché dobbiamo sfuggire alle barre in avanti nel percorso per differenziarle dalle barre in avanti nella sintassi di espansione bash. Inoltre, non sfuggire alle barre in avanti nella stringa di sostituzione, quindi sembra anche incoerente.

Se non è presente alcun /httpdocs/percorso nel percorso corrente, non verranno eseguite sostituzioni e passerà alla directory corrente.

Ad esempio, la sostituzione sostituirà /a/b/c/httpdocs/e/f/gcon /a/b/c/httpdocse cdin quella directory.

La funzione deve trovarsi nell'attuale ambiente shell (come funzione o alias) poiché un processo figlio non può modificare la directory corrente del suo genitore. Questo è il motivo per cui dico di inserirlo nel tuo .bashrce non in uno script di shell.


Per inciso, vale la pena ricordare che questo ti porterà il più in alto possibile nella gerarchia (che è probabilmente il caso d'uso più utile comunque).
Ibrahim,

3

Puoi anche inserire qualcosa di simile nel tuo profilo:

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

La semplice digitazione cdhti porterà alla httpdocsdirectory più in alto nel tuo percorso attuale.


2

Non risolve completamente il tuo problema, ma risparmia cd ../../../../../../un po '. Ho preso in prestito questo dal post dell'utente sconosciuto qui .


su N

salta N directory nella struttura delle directory

Invece di scrivere

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

scrivi e basta

up 4

e a

cd -    

ti riporterà indietro

Inserisci la funzione nel tuo .bashrc per usarla.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.