Les commandes pushd et popd sont des builtins du shell qui gèrent une pile de répertoires. Là où cd remplace le répertoire courant sans mémoire, pushd empile chaque chemin visité et popd dépile pour revenir en arrière. Comprendre cette pile transforme la navigation terminal en un enchaînement de sauts précis, sans retaper de longs chemins absolus.
Pile de répertoires dans Bash : le mécanisme à connaître avant tout
La pile de répertoires fonctionne comme une structure LIFO (last in, first out). Chaque appel à pushd ajoute le répertoire courant au sommet de la pile puis change vers le répertoire passé en argument. Chaque appel à popd retire l’entrée du sommet et ramène le shell dans le répertoire ainsi exposé.
La commande dirs affiche l’état de la pile à tout moment. Le premier élément listé est toujours le répertoire courant. Les suivants sont ceux empilés précédemment, du plus récent au plus ancien.
Un point souvent négligé : pushd et popd sont des commandes intégrées au shell, pas des binaires externes. Leur comportement dépend du shell utilisé (Bash, Zsh, Fish), pas du système d’exploitation. Deux machines sous Zsh, l’une sous Linux et l’autre sous macOS, produiront exactement le même résultat. Cette portabilité entre plateformes permet de construire un workflow réutilisable à condition de standardiser le shell.

Enchaîner pushd et popd dans un workflow terminal courant
Le cas d’usage le plus direct est le va-et-vient entre deux ou trois répertoires de travail. Prenons un projet avec un dossier source, un dossier de configuration et un dossier de logs.
Depuis le répertoire principal du projet, un premier pushd ./src empile le répertoire principal et bascule dans src. Un deuxième pushd ../config empile src et bascule dans config. À ce stade, la pile contient trois entrées visibles avec dirs : config au sommet, puis src, puis le répertoire principal.
Pour revenir à src, un simple popd suffit. Pour remonter ensuite au répertoire principal, un second popd fait le travail. Aucun chemin à retaper, aucune ambiguïté.
Avantage concret par rapport à cd
Avec cd, le raccourci cd - ne retient qu’un seul répertoire précédent. Dès qu’un troisième répertoire entre en jeu, le chemin intermédiaire est perdu. La pile de pushd/popd conserve autant de niveaux que nécessaire, ce qui élimine les cd ../../quelque-chose à rallonge.
- Deux répertoires :
cd -fonctionne, mais pushd reste plus lisible dans un script - Trois répertoires ou plus : seule la pile maintient la trace complète du parcours
- Scripts automatisés : pushd/popd garantit le retour au répertoire d’origine sans stocker de variable intermédiaire
Indices positionnels de popd pour réorganiser la pile
La plupart des tutoriels présentent popd comme un simple retour en arrière. La commande accepte pourtant des indices qui ouvrent des usages plus fins.
popd +0 (ou popd sans argument) retire le sommet de la pile et change de répertoire. En revanche, popd +1 retire une entrée spécifique sans changer de répertoire courant. Cette distinction permet de nettoyer la pile, par exemple pour supprimer un répertoire devenu inutile, sans provoquer de déplacement non désiré.
Avec pushd +N, la rotation fonctionne en sens inverse : l’entrée à la position N est ramenée au sommet et devient le répertoire courant. On peut ainsi naviguer dans la pile sans la vider, en faisant tourner les entrées comme dans une file circulaire.
Exemple de nettoyage sélectif
Supposons une pile de quatre répertoires après plusieurs pushd successifs. Le deuxième n’est plus utile. Un popd +1 le retire proprement. Le reste de la pile conserve son ordre, et le répertoire courant ne bouge pas. Ce mécanisme est particulièrement utile dans les scripts longs où la pile grandit au fil des étapes.

Pushd et popd dans les scripts shell : fiabilité du retour au répertoire d’origine
Dans un script Bash, changer de répertoire avec cd sans précaution crée un risque : si le script échoue en cours de route, il laisse le shell dans un répertoire imprévu. Le couple pushd/popd résout ce problème de façon structurelle.
Le patron classique consiste à ouvrir un bloc avec pushd, exécuter les opérations, puis refermer avec popd. Même en cas d’erreur intermédiaire, un popd placé dans un trap ou à la fin du bloc ramène le shell au point de départ.
pushd /chemin/cible > /dev/nullpour entrer silencieusement dans le répertoire de travail- Exécution des commandes nécessaires (compilation, copie, tests)
popd > /dev/nullpour revenir au répertoire initial sans polluer la sortie standard
La redirection vers /dev/null mérite attention. Par défaut, pushd et popd affichent la pile après chaque opération. Dans un script, rediriger la sortie évite un bruit inutile dans les logs et rend le résultat plus lisible.
Différences entre Bash et Zsh sur la gestion de la pile
Bash et Zsh implémentent tous deux pushd et popd, mais quelques différences de comportement méritent d’être connues pour éviter les surprises.
Zsh propose une option AUTO_PUSHD qui fait en sorte que chaque appel à cd empile automatiquement le répertoire quitté. Activer cette option transforme de facto tout cd en pushd, ce qui donne une pile toujours alimentée sans effort. Bash ne dispose pas de cet automatisme natif.
Les shells modernes comme Fish adoptent une approche différente : Fish intègre une pile de répertoires accessible via des raccourcis dédiés (prevd, nextd) et ne reconnaît pas pushd/popd en tant que tels. Pour un workflow portable entre Bash et Zsh, pushd/popd reste le dénominateur commun le plus fiable.
La gestion des indices (+N) est identique entre Bash et Zsh dans la grande majorité des cas. La principale source de confusion vient de l’option PUSHD_MINUS dans Zsh, qui inverse le sens des indices positifs et négatifs. Vérifier la configuration active du shell avant de scripter avec des indices évite des déplacements inattendus.
Construire un workflow terminal autour de pushd et popd demande surtout de prendre l’habitude d’empiler avant chaque déplacement. Une fois le réflexe acquis, la pile remplace les chemins absolus, les variables temporaires et les cd - limités à un seul niveau. Le gain se mesure surtout dans les scripts et les sessions longues où les allers-retours entre répertoires se multiplient.

