Dans un script Bash, découper un chemin avec cut, awk ou une série de sed devient vite fragile. Un espace dans le nom, un slash final ou un fichier sans extension suffit à faire dérailler le résultat. basename et dirname sont faits pour cette tâche : l’un récupère le dernier élément, l’autre conserve le dossier parent.
Je vous montre les cas utiles, les pièges à éviter et une façon de les intégrer proprement dans un script réel. Le point important : ces commandes décomposent une chaîne de chemin, mais elles ne valident pas que le fichier existe.
Récupérer le nom et le dossier
basename renvoie le dernier composant du chemin. dirname renvoie tout ce qui précède ce composant :
chemin="/var/log/nginx/access.log"
basename "$chemin"
dirname "$chemin"
La sortie est respectivement access.log puis /var/log/nginx. Les guillemets autour de la variable ne sont pas décoratifs. Sans eux, un chemin contenant un espace est découpé en plusieurs arguments par le shell.
Les deux commandes acceptent aussi un chemin relatif :
chemin="sauvegardes/serveur web/config.tar.gz"
echo "Fichier : $(basename "$chemin")"
echo "Dossier : $(dirname "$chemin")"
Ici, le nom récupéré est config.tar.gz et le dossier est sauvegardes/serveur web. Le shell exécute correctement la substitution parce que chaque expansion de $chemin reste entre guillemets.
Retirer un suffixe avec basename
Vous pouvez demander à basename de retirer un suffixe final. C’est pratique pour construire le nom d’un fichier de sortie, mais le motif est retiré tel quel : il ne s’agit pas d’une détection intelligente de format.
fichier="rapport.2026-08-07.tar.gz"
basename "$fichier" .gz
basename "$fichier" .tar.gz
Le premier appel enlève uniquement .gz et renvoie rapport.2026-08-07.tar. Le second enlève le suffixe complet et renvoie rapport.2026-08-07. Si le suffixe n’est pas présent à la fin, le nom reste inchangé.
Pour renommer une copie en gardant le dossier d’origine, vous pouvez combiner les deux commandes :
source="/srv/archives/configuration.tar.gz"
dossier=$(dirname "$source")
nom=$(basename "$source" .tar.gz)
destination="$dossier/$nom.verifie.tar.gz"
printf 'Source : %s\n' "$source"
printf 'Destination : %s\n' "$destination"
Le chemin de destination est construit à partir de valeurs séparées, puis réassemblé avec des guillemets. Cette méthode évite de parser manuellement les slashs et conserve les espaces éventuels.
Gérer les slashs finaux
Un slash final change le dernier composant traité. Avec GNU basename et dirname, les slashs terminaux sont ignorés dans les cas courants :
chemin="/var/lib/docker/"
basename "$chemin"
dirname "$chemin"
Le résultat est docker pour basename et /var/lib pour dirname. Si vous devez préserver la différence entre un fichier et un dossier, ne vous fiez pas au texte seul. Vérifiez le système de fichiers :
if [ -d "$chemin" ]; then
echo "C’est un dossier"
elif [ -f "$chemin" ]; then
echo "C’est un fichier"
else
echo "Chemin absent ou type non géré" >&2
exit 1
fi
basename et dirname ne testent pas l’existence. Un chemin inventé produit quand même une réponse textuelle. Ajoutez donc -d ou -f avant une copie, une suppression ou une modification.
Les intégrer dans un script Bash
Dans un script, contrôlez aussi les arguments reçus. L’exemple suivant crée un dossier de sortie à côté du fichier fourni, sans supposer que son nom est simple :
#!/usr/bin/env bash
set -u
if [ "$#" -ne 1 ]; then
printf 'Usage : %s FICHIER\n' "$0" >&2
exit 64
fi
fichier=$1
if [ ! -f "$fichier" ]; then
printf 'Fichier introuvable : %s\n' "$fichier" >&2
exit 1
fi
dossier=$(dirname -- "$fichier")
nom=$(basename -- "$fichier")
sortie="$dossier/traite-$nom"
printf 'Fichier source : %s\n' "$nom"
printf 'Fichier sortie : %s\n' "$sortie"
L’option -- signale la fin des options. Elle protège les cas où un nom commence par un tiret. Le script vérifie ensuite le fichier avant de construire la sortie. Vous pouvez remplacer les printf par l’opération voulue, après avoir ajouté un test d’écrasement si nécessaire.
Pour essayer ce script sans toucher à vos données, créez un chemin de test avec des espaces :
mkdir -p "./test chemins"
printf 'ligne de test\n' > "./test chemins/rapport final.txt"
./chemins.sh "./test chemins/rapport final.txt"
rm -rf "./test chemins"
Quand préférer une autre méthode
Pour une simple séparation nom/dossier, basename et dirname sont lisibles et disponibles sur les distributions Linux courantes. Ne les utilisez pas pour analyser plusieurs lignes de chemins non contrôlés : un retour à la ligne dans un nom de fichier peut rendre une sortie texte ambiguë.
Si vous parcourez réellement des fichiers, préférez un flux nul avec find -print0 et while IFS= read -r -d ''. Si vous manipulez uniquement un chemin reçu en argument, les guillemets et les tests d’existence suffisent généralement.
La documentation de basename et la page de manuel de dirname détaillent les options disponibles. Pour les scripts qui recherchent ensuite un exécutable, vous pouvez aussi relire le guide sur PATH sous Linux.
Testez d’abord avec un chemin contenant des espaces, un slash final et plusieurs suffixes. C’est là que les scripts bricolés avec une découpe manuelle cassent le plus souvent.