Il est des fois où on erre parmi les répertoires depuis son terminal : cd par-ci, cd par-là… Avancer dans 3 sous-dossiers, remonter de 7… Parfois on ne sait plus combien de « .. » il va falloir enchaîner… Pourtant, le nom du dossier (lointain parent), lui, il est juste là, et ce fichu principe de remonter les niveaux un à un… En plus avec la quasi assurance de devoir saisir, dans une seconde commande, un ultime « cd .. » … Bref, des fois, c’est quand-même chiant ! Une petite fonction en Bash, et les « cd ../../.. […] /../../.. » vont vite décéder.
Dans la fonction ci-dessous, les commandes classiques que sont test, pwd et sed, vont nous permettre de remonter au répertoire qui aura été saisi en argument (pourvu que celui-ci existe).
function dcd ()
{
if test `pwd | sed -e "s/\(.*\<${1}\>.*\)/\!/g"` = '!'
then
niveaux=`pwd | sed -e "s;.*\<${1}\>/*\(.*\);\1;" -e "s/\<[^/]*\>/../g"`
test ${#niveaux} -gt 1 && cd $niveaux
fi
}
Avant que vous ne soyez pris(e) de panique au vu de ce bout de code (les expressions régulières ont parfois un côté obscur), quelques explications s’imposent peut-être…
Le test qui conditionne le if, permet de vérifier que le paramètre $1 constitue bien le nom d’un des répertoires supérieurs :
- on exécute d’abord pwd pour connaître le chemin complet
- sed permet ensuite de transformer tout ce chemin en un seul caractère « ! », à l’unique condition que le paramètre $1 soit bien trouvé (en tant que mot au sens des expressions régulières)
- si la commande retourne « ! », alors le contenu du if est exécuté
Une fois dans le if, avec l’assurance que le répertoire cible existe, le nombre de répertoires à remonter va être stocké dans une variable « niveaux ». En voici le principe :
- on exécute encore une fois pwd, toujours pour connaître le chemin complet
- une première expression est soumise à la commande sed (premier « -e » ), afin de retirer de la chaîne tous les caractères devant le répertoire cible (donc en amont), et le répertoire cible avec
- une seconde expression est ensuite soumise à sed (deuxième « -e » ), pour remplacer chacun des répertoires encore présents par les fameux deux points « .. »
- en testant la longueur de la chaîne de « ../../.. » produite, on s’assure enfin de devoir remonter un certain nombre de niveaux, et c’est à cette seule condition qu’est exécuté le cd $niveaux
Après enregistrement de ce script dans un fichier, et un petit « source … » sur ce même fichier, la commande dcd fraîchement créée peut enfin être testée dans le terminal.
# Là, ça marche :
mynameis@localhost:/etc/locale/fr/LC_MESSAGES$ dcd locale
mynameis@localhost:/etc/locale$
# Là, ça marche pas, et heureusement :
mynameis@localhost:/etc/locale/fr/LC_MESSAGES$ dcd et
mynameis@localhost:/etc/locale/fr/LC_MESSAGES$
Bon… Tout ça c’est bien, mais c’est un peu lourd-dingue alors qu’il n’y a pas de quoi casser trois pattes à un canard… Voici une deuxième solution qui a le mérite d’être plus robuste, tout en étant nettement plus lisible.
function dcd ()
{
increment=0
for directory in `pwd | sed -e "s/ /5PAC3/g" -e "s/\// /g"`
do
directory=`echo $directory | sed "s/5PAC3/ /g"`
test "$increment" -eq 1 && cd ..
test "$directory" = "$1" && increment=1
done
}
Le principe de cette nouvelle version est très simple :
- à l’aide de pwd, on dresse la liste des dossiers en amont, que l’on sépare par des espaces avec sed
- la chaîne «5PAC3», comme pour un précédent article, nous permet de sauvegarder les éventuels espaces dans le nom des répertoires
- pour chaque répertoire listé, on exécute alors le contenu de la boucle for :
- on recouvre d’abord les espaces précédemment convertis en chaîne «5PAC3»
- dès que l’on arrive au dossier cible, on le signale en mettant à jour la variable $increment
- si le dossier cible a été dépassé dans la liste, alors on sait qu’il faut remonter d’un niveau via un « cd .. » , à chaque nouveau passage
Les solutions ne manquent donc pas, et il y en a, à n’en pas douter, sûrement d’autres ; et même meilleures que ces deux-ci.

Publié sous licence Creative Commons.