Bash CD jusqu'à dans certains dossiers

16

Je fais beaucoup de travail dans Magento, tout comme beaucoup de gens avec qui je travaille, et ça devient ennuyeux de devoir taper:

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

Pour ne trouver que quelques répertoires dans votre dossier racine 'httpdocs', j'essaie donc de créer un script qui suit ce pseudo-code:

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

Cela semble assez simple, je suppose que je devrais faire une sorte de grep pour vérifier si la dernière partie du répertoire de travail actuel est httpdocs, sinon continuer à monter d'un niveau jusqu'à ce qu'il soit vrai.

J'ai cherché à apprendre bash pour cela, bien qu'il semble qu'il y ait déjà quelque chose de similaire qui soit similaire, et la syntaxe me laisse perplexe sans fin.

user652650
la source

Réponses:

8

Cela doit être une fonction shell , pas un script, car un script s'exécute dans un nouveau shell (et ne peut donc pas changer le répertoire du shell d'origine).

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

Vous pouvez bien sûr nommer la fonction comme bon vous semble.

Quelques explications: le premier test ( $PWD != '/') est une sécurité intégrée au cas où vous le feriez cdrootlorsque vous n'êtes pas dans un dossier httpdocs. Cela s'arrêtera lorsque vous arriverez à la racine.

Le deuxième test ( ${PWD##*/} != 'httpdocs') est un peu plus compliqué. $PWDest une variable contenant le chemin du répertoire courant. ${PWD##*/}coupe tout jusqu'à et y compris la dernière barre oblique.

cjm
la source
L'inconvénient de celui-ci est que vous perdez votre capacité à faire juste cd -après pour revenir là où vous étiez.
Ezequiel Muns
27

J'ai une fonction appelée uptodans mon .bashrc qui vous permet d'accéder à n'importe quel répertoire du chemin actuel par son nom:

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

J'ai également l'achèvement de cette fonction, de sorte qu'elle me donne des noms de répertoire valides et l'achèvement lorsque j'appuie sur l'onglet:

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

De plus, j'ai une autre fonction jdqui me permet de sauter dans n'importe quel répertoire en dessous du répertoire actuel:

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

Exemple:

[/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
la source
Vous pouvez également ajouter un alias pour upto httpdocs.
cjm
@drogbane: jdne semble pas fonctionner dans tous les cas, pourriez-vous expliquer comment cela fonctionne?
Cesar
@Cesar utilise globstar ( **). Pour activer cette fonctionnalité dans votre shell bash, utilisez shopt -s globstar.
Dogbane
2
C'est si brillamment fait, j'aimerais pouvoir voter deux fois.
droope
1
J'ai inclus une détection et une activation dynamiques de shopt dans la jdfonction, voir gist.github.com/Rob--W/5888648 . Je ne l'ai testé qu'avec Bash 4.2.45, donc YMMV.
Rob W
5

La fonction bash la plus simple à laquelle vous pouvez .bashrcpenser (simple car elle n'utilise pas de boucles ou de processus externes) est:

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

Celui - ci utilise la substitution modèle d' expansion des paramètres pour tout remplacer après /httpdocs/dans $PWDavec `/ httpdocs. Cela semble très compliqué car nous devons échapper aux barres obliques dans le chemin pour les différencier des barres obliques dans la syntaxe d'extension bash. De plus, n'échappez pas aux barres obliques dans la chaîne de remplacement, de sorte qu'il semble également incohérent.

S'il n'y en a pas /httpdocs/dans le chemin en cours, aucune substitution ne sera effectuée et il ne fera que passer au répertoire en cours.

Par exemple, la substitution sera remplacée /a/b/c/httpdocs/e/f/gpar /a/b/c/httpdocset cddans ce répertoire.

La fonction doit se trouver dans votre environnement shell actuel (en tant que fonction ou alias), car un processus enfant ne peut pas modifier le répertoire actuel de son parent. C'est pourquoi je dis de le mettre dans votre .bashrcet non dans un script shell.

camh
la source
Soit dit en passant, il convient de mentionner que cela vous amènera le plus haut possible dans la hiérarchie (ce qui est probablement le cas d'utilisation le plus utile de toute façon).
Ibrahim
3

Vous pouvez également mettre quelque chose comme ça dans votre profil:

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

La simple saisie vous cdhamènera au httpdocsrépertoire le plus haut de votre chemin actuel.

Tapis
la source
2

Cela ne résout pas complètement votre problème, mais cela vous fera économiser cd ../../../../../../un peu. J'ai emprunté ceci au post de l' utilisateur inconnu ici .


en haut N

sauter N répertoires dans l'arborescence des répertoires

Au lieu de taper

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

vous venez de taper

up 4

et un

cd -    

vous ramènera

Mettez la fonction dans votre .bashrc pour l'utiliser.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
boehj
la source