CyberSDF

Reprenez la main sur votre numérique

Raccourcis cd : revenir au dossier précédent sans retaper le chemin

cd – ramène au dossier précédent sans retaper le chemin, parce que bash relit la variable OLDPWD posée au changement de dossier précédent. L’opérande – est converti en $OLDPWD avant la tentative de changement, écrit la documentation GNU Bash, et la commande échoue si ce dossier a été supprimé entre-temps. Deux chemins suffisent donc à couvrir l’aller-retour le plus courant, à condition de rester dans le même terminal.

Sommaire
  1. cd – écrit le chemin retrouvé sur la sortie standard
  2. Huit raccourcis et la sortie qu’ils produisent
  3. pushd empile le dossier quitté au lieu de le perdre
  4. Un dossier supprimé dans la pile fait échouer popd
  5. Le tiret seul reste l’ancien dossier, même après un double tiret
  6. /bin/sh refuse pushd et accepte cd –
  7. La pile reste dans le shell et ne coûte rien aux programmes lancés
  8. Les documents qui font foi pour ces commandes

Chaque cd réussi réécrit OLDPWD, si bien que deux cd de suite oublient le premier dossier. Rien à installer pour corriger cela : cd, pushd et popd sont des builtins de bash, et les guides Linux qui couvrent les bases du terminal les abordent avec pwd et ls. Pour plusieurs allers-retours, pushd et popd remplacent ce retour unique par une pile où l’on circule par numéro.

cd /etc/apt
cd /var/log
cd -

L’écran affiche :

/etc/apt

pwd renvoie ensuite /etc/apt.

cd – écrit le chemin retrouvé sur la sortie standard

cd – ne se contente pas de changer de dossier : la commande écrit aussi le chemin absolu du dossier retrouvé, et cette écriture part sur la sortie standard. La documentation GNU Bash rattache ce comportement à deux cas, un dossier trouvé via CDPATH ou l’opérande – placé en premier argument, et elle précise qu’il vaut même dans un shell non interactif. Sur Ubuntu 24.04.4 LTS, bash 5.2.21 imprime ainsi /etc/apt après un cd – lancé depuis /var/log.

La spécification POSIX décrit la même sortie : le chemin absolu du nouveau dossier est écrit après la mise à jour de PWD. Cette écriture se récupère dans un script avec chemin=$(cd -), alors qu’un simple cd sans tiret n’écrit jamais rien. Une variante évite l’écriture quand elle gêne, cd ~-, qui vise le même dossier par l’expansion de la tilde.

cd /etc/apt
cd /var/log
chemin=$(cd -)
printf '%s\n' "$chemin"

L’écran affiche :

/etc/apt

Pour savoir où l’on se trouve avant de taper la commande, afficher le dossier courant dans l’invite évite des retours inutiles.

Huit raccourcis et la sortie qu’ils produisent

Un raccourci de navigation se juge sur deux choses : la ligne écrite par bash et le dossier où l’on atterrit. Le tableau donne les deux pour huit commandes, relevées sur bash 5.2.21 livré par Ubuntu 24.04.4 LTS. Trois d’entre elles ne déplacent personne, puisqu’elles lisent seulement l’état de la pile. Les index commencent à zéro et le dossier courant occupe la position 0, comme le montre dirs -v.

popd sans argument retire le sommet de la pile et ramène au dossier précédent, ce que la documentation GNU Bash résume par popd +0. Retirer une entrée qui n’est pas le sommet, par exemple popd +1, ne change pas le dossier courant, seule la pile rétrécit. Une écriture de confort complète la règle, dirs remplaçant le dossier personnel par un tilde et dirs -l rétablissant le chemin complet.

Commande Ce que bash affiche Dossier courant après la commande
cd /var/log rien /var/log
cd rien le dossier de $HOME
cd - le chemin absolu du dossier précédent le dossier précédent
cd ~- rien le dossier précédent
pushd /etc la pile complète sur une ligne /etc
popd la pile restante sur une ligne le dossier du nouveau sommet
popd +1 la pile restante sur une ligne inchangé
dirs -v une ligne par entrée, précédée de son numéro inchangé

pushd empile le dossier quitté au lieu de le perdre

pushd fait deux choses en un seul geste : le dossier courant part sur la pile et la commande change pour le dossier demandé. La documentation GNU Bash précise que bash lance dirs après chaque pushd ou popd réussi, ce qui explique la ligne de chemins qui suit la commande. L’option -n modifie le comportement en n’ajoutant qu’une entrée, sans changer de dossier, et pwd confirme alors que rien n’a bougé.

Trois entrées suffisent à voir le mécanisme. Les numéros affichés par dirs -v restent stables : 0 pour le dossier courant, puis 1, 2 et ainsi de suite dans l’ordre d’empilement. pushd +2 fait tourner la pile pour amener l’entrée numéro 2 au sommet, ce que le manuel appelle une rotation. Cette pile rend le même service que naviguer vers le dossier précédent avec cd –, mais sur autant de dossiers que nécessaire.

cd /etc
pushd /var/log
pushd /usr/share/doc
dirs -v
popd
dirs -v

L’écran affiche :

 0  /usr/share/doc
 1  /var/log
 2  /etc
/var/log /etc
 0  /var/log
 1  /etc

Un dossier supprimé dans la pile fait échouer popd

Une pile garde des chemins, pas des dossiers ouverts : si le dossier disparaît, popd refuse d’y entrer et le message nomme popd, pas cd. La même mécanique explique les deux autres refus, un dossier empilé inexistant au moment du pushd et une pile vidée par dirs -c. Sur Ubuntu 24.04.4 LTS avec bash 5.2.21, les messages sont ceux-ci. Le code source de bash confirme ces libellés, et l’entrée fautive reste dans la pile, le dossier courant ne bouge pas.

Deux gestes remettent la pile d’aplomb : dirs -v pour repérer le numéro de l’entrée morte, puis popd +2 pour la retirer sans changer de dossier, ou dirs -c pour tout effacer et repartir du dossier courant. Un pushd raté n’ajoute rien du tout, puisque bash empile après le changement de dossier et non avant.

bash: pushd: /aucun/dossier: No such file or directory
bash: popd: /tmp/x1: No such file or directory
bash: popd: directory stack empty
bash: cd: /tmp/x2: No such file or directory

Le quatrième message vient d’un cd – dont la cible a été supprimée entre les deux passages. Les repères pour se déplacer dans les fichiers et les répertoires aident à retrouver le bon chemin avant de relancer la commande.

Le tiret seul reste l’ancien dossier, même après un double tiret

Un dossier nommé – ne s’atteint pas avec cd — – : l’opérande tiret est traduit en $OLDPWD avant même que les options soient digérées, et la commande repart donc vers le dossier précédent. Sur Ubuntu 24.04.4 LTS, cd ./- reste la voie d’entrée, ce que la spécification POSIX recommande aussi en conseillant d’écrire ./ devant un nom de dossier fourni par une variable. La règle vaut pour tout chemin construit dans un script.

L’opérande vide pose un autre problème de version. POSIX Issue 8 exige un message d’erreur et un statut non nul pour cd “”, alors que bash 5.2.21 se contente de ne rien faire et renvoie 0, ce qui laisse un script continuer dans le mauvais dossier. Les notes de version de bash annoncent la correction pour bash 5.3, où un chemin vide devient une erreur.

cd ./-
pwd

L’écran affiche :

/tmp/-
[ -n "$dossier" ] || exit 1
cd "$dossier"

Une variable vide arrête le script à la première ligne.

/bin/sh refuse pushd et accepte cd –

/bin/sh pointe vers dash sur Ubuntu 24.04.4 LTS, et dash répond dash: 1: pushd: not found, alors que cd – y fonctionne parce que POSIX impose l’opérande tiret. Un script déclaré en sh qui utilise la pile de dossiers ne démarre donc pas, et l’erreur n’apparaît qu’à l’exécution de la ligne. Passer la première ligne à #!/bin/bash règle le problème sur les distributions qui livrent bash en standard.

Le suivi des paquets Debian donne les versions en circulation : Debian 12 embarque bash 5.2.15-2, Debian 13 est passée à 5.2.37-2 et les dépôts testing et unstable pointent 5.3-4. La page de manuel Debian de bookworm documente la version 5.2.15-2+b8 et donne pour CDPATH l’exemple . : ~ : /usr. Le choix de l’interpréteur fait partie des réflexes de base quand on apprend à écrire un script shell.

dash -c 'pushd /tmp'
dash -c 'cd /tmp; cd -'

L’écran affiche :

dash: 1: pushd: not found
/tmp

La pile reste dans le shell et ne coûte rien aux programmes lancés

DIRSTACK vit dans le shell courant et n’est pas exportée : sur Ubuntu 24.04.4 LTS, env lancé après deux pushd affiche PWD et OLDPWD mais aucune ligne DIRSTACK. Un programme externe hérite donc du dossier de travail, jamais de la pile, et un sous-processus créé par bash ne voit pas non plus les entrées empilées. Cette variable n’existe pas dans dash, où tout ce qui touche à la pile disparaît.

Le nombre d’entrées n’est pas plafonné par la documentation GNU Bash, et le code de pushd agrandit le tableau interne par blocs de dix emplacements. Un test de 41 entrées sur Ubuntu 24.04 est passé sans erreur, et rien de la pile n’est écrit sur disque puisqu’elle vit en mémoire. La mémoire du shell reste la seule dépense engagée par ces commandes.

Combien d’entrées la pile de dossiers peut-elle contenir ?

La documentation GNU Bash ne fixe aucune limite, et le code de pushd agrandit le tableau DIRSTACK par blocs de dix emplacements. Sur Ubuntu 24.04.4 LTS, une pile de 41 entrées s’est construite sans message d’erreur. Le seul coût est la mémoire du shell, quelques dizaines d’octets par chemin.

cd – ou pushd : lequel choisir pour un script ?

Un script en sh s’exécute avec dash sur Ubuntu 24.04.4 LTS, où pushd répond dash: 1: pushd: not found, alors que cd – fonctionne parce que POSIX l’impose. Dans un script bash, pushd apporte la pile complète dès qu’il faut revenir plusieurs fois. Écrire cd “$OLDPWD” évite la ligne que cd – imprime sur la sortie standard.

Que fait popd quand un dossier empilé a été supprimé ?

popd refuse d’entrer dans un chemin disparu et affiche bash: popd: /tmp/x1: No such file or directory sous bash 5.2.21. L’entrée fautive reste dans la pile et le dossier courant ne bouge pas. dirs -v donne son numéro, popd +2 la retire sans changer de dossier, et dirs -c vide toute la pile.

Pourquoi cd “” ne renvoie-t-il aucune erreur sous bash 5.2 ?

Sur Ubuntu 24.04.4 LTS, cd “” renvoie 0 et laisse le dossier courant en place, alors que POSIX Issue 8 exige un message d’erreur et un statut non nul. Les notes de version de bash annoncent une erreur à partir de bash 5.3. Un script doit donc tester la variable avant l’appel, par exemple avec [ -n “$dossier” ] || exit 1.

Les programmes lancés après un pushd voient-ils la pile ?

Non : bash exporte PWD et OLDPWD, pas DIRSTACK. Sur Ubuntu 24.04.4 LTS, env lancé après deux pushd montre les deux premières variables et aucune ligne DIRSTACK. Un programme externe travaille donc dans le bon dossier sans savoir par où l’on est passé.

Comment revenir à un dossier empilé qui n’est pas le précédent ?

dirs -v numérote les entrées à partir de zéro, le dossier courant occupant la position 0. pushd +2 amène l’entrée 2 au sommet et change de dossier, alors que cd ~2 y va sans toucher à la pile, l’expansion de la tilde acceptant le numéro d’une entrée. Sur bash 5.2.21, cd ~1 après deux pushd place dans le dossier affiché en position 1.

Les documents qui font foi pour ces commandes

Le manuel de référence de GNU Bash décrit cd, pushd, popd et dirs dans un même document, avec les valeurs par défaut des options shopt et la liste des variables PWD, OLDPWD et DIRSTACK. La page de manuel Debian reprend la même matière pour le paquet livré par bookworm, avec son numéro de version. Le dépôt Savannah publie le code des builtins et les notes de version, où figure la correction du chemin vide annoncée pour bash 5.3.

La spécification POSIX Issue 8 fait autorité sur l’opérande tiret, l’écriture du chemin sur la sortie standard et le sort de l’opérande vide, trois points où bash 5.2 et la norme ne disent pas la même chose. Le suivi des paquets Debian donne enfin les versions livrées dans le détail de chaque distribution.