Popd avancé : astuces de power user pour dompter la ligne de commande

La commande popd retire le dernier répertoire empilé par pushd et y repositionne le shell. Cette mécanique de pile LIFO (last in, first out) existe dans Bash, Zsh, PowerShell et même l’invite de commandes Windows. La plupart des guides s’arrêtent à la syntaxe de base. Cet article va plus loin : rotations de pile, intégration dans des scripts, alias composites et pièges à éviter quand la pile se désynchronise.

La pile de répertoires : fonctionnement interne de pushd et popd

Avant d’exploiter popd, il faut comprendre ce que pushd dépose sur la pile. Chaque appel à pushd /chemin ajoute le répertoire courant au sommet de la pile, puis change le répertoire de travail vers /chemin. La commande dirs affiche l’état complet de la pile, du sommet (index 0) vers la base.

A lire également : Mafreebox.freebox.fr première connexion : les réglages à faire en priorité

popd dépile le sommet et revient au répertoire précédent. Sans argument, l’opération est simple. Avec un argument positionnel (popd +2 par exemple), Bash retire l’entrée à l’index spécifié sans forcément changer de répertoire, sauf si cet index est 0.

Cette distinction est la source de la majorité des erreurs dans les scripts. Retirer une entrée au milieu de la pile ne déplace pas le shell. Seul popd sans argument ou popd +0 provoque un changement de répertoire effectif.

A lire aussi : Webmail ac Rennes connexion depuis un nouvel ordinateur : les paramètres à vérifier

Jeune développeuse utilisant un terminal zsh avec gestion de pile de répertoires dans un loft de coworking

Rotations de pile avec popd : naviguer sans cd

La pile de répertoires n’est pas qu’un historique passif. En combinant pushd avec des index et popd, on obtient une navigation circulaire entre plusieurs dossiers de travail.

Rotation avant et arrière

pushd +1 fait tourner la pile d’un cran vers la gauche : le deuxième répertoire passe en tête et devient le répertoire courant. pushd -0 effectue la rotation inverse. Associé à popd pour nettoyer les entrées devenues inutiles, ce mécanisme remplace les successions de cd et cd - dès qu’on travaille sur trois dossiers ou plus.

Cas concret : trois répertoires de travail

Supposons un projet avec un dossier source, un dossier de build et un dossier de déploiement. Trois pushd successifs empilent ces chemins. Ensuite, pushd +1 et pushd +2 permettent de basculer entre eux sans retaper les chemins. Quand le build est terminé, popd +1 retire le dossier de build de la pile sans quitter le répertoire courant.

  • pushd ~/projet/src puis pushd ~/projet/build puis pushd ~/projet/deploy : trois entrées empilées
  • pushd +2 : bascule vers src, la pile tourne
  • popd +1 : retire build de la pile, le shell reste dans src

Popd dans les scripts shell : fiabiliser le retour au répertoire d’origine

Un usage fréquent de pushd/popd dans les scripts consiste à garantir que le répertoire de travail est restauré après une opération, même en cas d’erreur. Le pattern classique :

pushd /un/chemin > /dev/null en début de bloc, puis popd > /dev/null en fin de bloc. La redirection vers /dev/null supprime l’affichage de la pile, qui pollue la sortie standard des scripts.

Le piège du exit prématuré

Si le script quitte avant le popd, la pile reste corrompue pour la session appelante (dans le cas d’un script sourcé avec source ou .). Pour un script exécuté dans un sous-shell (la méthode standard avec ./script.sh), la pile du sous-shell est détruite à la fin, sans conséquence. La distinction est capitale.

Pour les scripts sourcés, un trap sur EXIT garantit le popd :

pushd /chemin > /dev/null; trap 'popd > /dev/null' EXIT

Ce pattern est plus robuste qu’une variable OLDPWD sauvegardée manuellement, parce que la pile pushd/popd gère nativement l’imbrication. Deux pushd successifs nécessitent deux popd, et la pile les ordonne correctement, là où des variables manuelles exigent un nommage distinct pour chaque niveau.

Vue aérienne d'un bureau de power user avec terminal bash, livre de scripting et notes manuscrites sur les commandes popd

Alias et fonctions autour de popd pour Bash et Zsh

Les alias simples accélèrent la navigation quotidienne. Quelques exemples concrets qui vont au-delà du alias p='popd' trivial.

Fonction de nettoyage complet de la pile

Bash ne propose pas de commande native pour vider toute la pile d’un coup. Une fonction dédiée comble ce manque :

clearstack() { while popd 2>/dev/null; do :; done; }

Cette boucle appelle popd jusqu’à ce que la pile soit vide. La redirection de stderr évite le message d’erreur sur le dernier appel (pile déjà vide).

Alias de navigation numérotée

Plutôt que de taper popd +2, certains utilisateurs créent des alias numérotés :

  • alias p1='popd +1' : retire la deuxième entrée de la pile
  • alias p2='popd +2' : retire la troisième entrée
  • alias pd='popd > /dev/null' : popd silencieux pour les scripts
  • alias ds='dirs -v' : affiche la pile avec les index, ce qui facilite le choix de l’argument à passer à popd

Zsh et l’option AUTO_PUSHD

Zsh propose l’option setopt AUTO_PUSHD, qui empile automatiquement chaque répertoire visité par cd. Combinée à setopt PUSHD_IGNORE_DUPS (évite les doublons), la pile se remplit sans intervention. Popd devient alors un vrai bouton « précédent », comparable à celui d’un navigateur web, mais pour le terminal.

Avec AUTO_PUSHD actif, la pile peut grossir vite. Zsh permet de la limiter avec DIRSTACKSIZE=15 dans le fichier .zshrc. Au-delà de cette taille, les entrées les plus anciennes sont automatiquement éliminées.

Différences entre popd Bash, Zsh et PowerShell

Le comportement de popd varie selon le shell, et ces variations créent des bugs subtils quand on porte un script d’un environnement à l’autre.

Dans Bash, popd affiche la pile restante après le retrait. Dans Zsh avec les options par défaut, le comportement est identique. PowerShell implémente Pop-Location (aliasé popd), mais la pile est gérée par un mécanisme distinct appelé location stack. PowerShell supporte même des piles nommées via Push-Location -StackName "MaPile", ce qui permet de maintenir plusieurs piles indépendantes.

Sous l’invite de commandes Windows (cmd.exe), popd a un comportement supplémentaire : si pushd a monté un chemin réseau UNC en tant que lecteur temporaire, popd supprime aussi cette lettre de lecteur. Ce détail est absent de Bash et Zsh, où les chemins réseau n’existent pas sous cette forme.

Quand un script doit fonctionner sur plusieurs shells, la méthode la plus portable reste de n’utiliser popd que sans argument, et de vérifier la présence de la commande avec type popd ou command -v popd avant de l’appeler.

Les plus plébiscités