Aller au contenu
Systeme

Basename et dirname : fiabiliser les chemins dans un script Bash

Avatar illustré de Julien Macé 4 min de lecture
Tux admin Linux sépare un nom de fichier et son dossier dans un chemin Bash
Basename récupère le dernier élément d’un chemin, tandis que dirname conserve le dossier parent.

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.

Tux admin Linux sépare un nom de fichier et son dossier dans un chemin Bash
Basename récupère le dernier élément d’un chemin, tandis que dirname conserve le dossier parent.

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.

Avatar illustré de Julien Macé

Julien Macé est administrateur systèmes et réseaux depuis plus de 15 ans. Principalement spécialisé dans Windows, il s’intéresse également aux systèmes Linux. Sur LinuxEnCaja, il vous propose des tutoriels gratuits pour installer, administrer et dépanner vos systèmes Linux.

Partager Facebook X WhatsApp LinkedIn Pinterest Reddit E-mail