Script Bash : detecter un fichier ou un dossier sans erreur

Script Bash : detecter un fichier ou un dossier sans erreur

Un script Bash fiable ne commence pas par copier, supprimer ou deplacer des fichiers. Il commence par verifier ce qui existe vraiment. Un chemin absent, un dossier confondu avec un fichier ou une permission manquante suffit a casser une sauvegarde, un deploiement ou une tache planifiee.

Pour detecter efficacement un fichier ou un dossier en Bash, utilisez test, sa forme entre crochets [ ], ou [[ ]] quand vous ciblez Bash. Les tests les plus utiles sont -f pour un fichier regulier, -d pour un dossier, -e pour une existence quelconque, puis -r, -w et -x pour les permissions.

En bref
  • ✓Utilisez -f pour verifier un fichier regulier et -d pour verifier un repertoire.
  • ✓e confirme quun chemin existe, quel que soit son type: fichier, dossier, lien, socket ou autre.
  • ✓Quotez toujours les variables de chemin: "$path" evite les erreurs avec espaces et caracteres speciaux.
  • ✓Testez aussi les permissions avec -r, -w ou -x avant de lire, ecrire ou executer.
  • ✓Dans un script important, retournez une erreur claire et un code de sortie plutot que de laisser une commande echouer plus loin.

Le reflexe de base : tester avant d'agir

La forme la plus portable est la commande test, souvent ecrite avec des crochets. Elle renvoie un code de sortie : 0 si la condition est vraie, 1 si elle est fausse, et une valeur superieure en cas d'erreur de syntaxe. Bash utilise ensuite ce code dans un if.

path="/var/log/app.log"

if [ -f "$path" ]; then
  echo "Fichier trouve"
else
  echo "Fichier absent"
fi

Les espaces autour des crochets sont obligatoires. [ est une commande, et ] doit etre un argument separe. Cette regle explique beaucoup d'erreurs de debutant. Ecrire [-f "$path"] n'est pas une variante compacte : c'est une autre commande invalide.

Le deuxieme reflexe est de toujours proteger les variables avec des guillemets doubles. Sans guillemets, un chemin comme Mes Documents/config.ini devient plusieurs arguments. Avec "$path", Bash garde le chemin comme une seule valeur.

Fichier, dossier ou chemin quelconque : choisir le bon test

Le bon test depend de ce que votre script va faire ensuite. Si vous devez lire un fichier de configuration, -f est plus precis que -e. Si vous devez copier des fichiers dans une destination, -d est le bon choix. Si vous voulez seulement savoir si un chemin est deja pris, -e suffit.

if [ -d "$target_dir" ]; then
  echo "Dossier pret"
fi

if [ -f "$config_file" ]; then
  echo "Configuration presente"
fi

if [ -e "$path" ]; then
  echo "Le chemin existe deja"
fi

Cette nuance evite des comportements dangereux. Un dossier peut exister avec le nom attendu d'un fichier. Un fichier peut exister a la place d'un dossier. Si vous utilisez seulement -e, le script croit que tout va bien, puis echoue plus loin ou ecrit au mauvais endroit. Le test doit correspondre a l'action suivante.

Besoin Test conseille Pourquoi
Lire un fichier de config [ -f "$file" ] Evite de confondre avec un dossier ou un lien special.
Verifier une destination [ -d "$dir" ] Confirme que le chemin est un repertoire utilisable.
Tester un chemin deja occupe [ -e "$path" ] Detecte n'importe quel type d'entree existante.
Ignorer un fichier vide [ -s "$file" ] Verifie existence et taille superieure a zero.
Flowchart de decision pour tester un fichier ou un dossier dans un script Bash
Le test doit suivre lintention du script: lire un fichier, ecrire dans un dossier, suivre un lien ou bloquer une operation risquee.

Tester les permissions avant de lire ou d'ecrire

Un fichier peut exister sans etre lisible. Un dossier peut etre present sans etre accessible en ecriture. C'est frequent avec des scripts lances par cron, un utilisateur systeme, un conteneur ou un service qui n'a pas les memes droits que votre session interactive.

if [ -r "$input_file" ]; then
  cat "$input_file"
else
  echo "Fichier illisible: $input_file" >&2
  exit 1
fi

Pour une destination, testez d'abord que c'est bien un dossier, puis qu'il est accessible en ecriture. Les deux conditions ne racontent pas la meme chose.

if [ ! -d "$output_dir" ]; then
  echo "Dossier absent: $output_dir" >&2
  exit 1
fi

if [ ! -w "$output_dir" ]; then
  echo "Dossier non inscriptible: $output_dir" >&2
  exit 1
fi

Ce style parait plus long, mais il gagne du temps quand le script tourne sans surveillance. L'erreur indique la cause exacte au lieu de laisser une commande cp, mv ou tar echouer plus loin avec un message moins clair.

Pour approfondir ce point, consultez reconnaître faux iPhone, qui traite plus précisément de reconnaître un faux iphone avant d’acheter.

Comparatif

Crochets simples ou doubles ?

Les deux formes existent, mais elles ne visent pas exactement le meme niveau de portabilite.

[ ]

Portable

Compatible POSIX, tres bon choix pour les scripts shell simples.

test

Equivalent

Même logique que les crochets, utile pour comprendre le code de sortie.

[[ ]]

Bash

Plus confortable dans Bash, notamment pour certaines comparaisons et motifs.

-a / -o

A eviter

Preferer && et || pour composer les tests de facon plus lisible et moins ambigue.

Composer plusieurs tests sans piege

Pour verifier qu'un fichier existe et qu'il est lisible, vous pouvez enchainer deux tests avec &&. Cette forme est claire et evite les ambiguites historiques de -a dans test.

if [ -f "$file" ] && [ -r "$file" ]; then
  echo "Fichier exploitable"
fi

Pour accepter soit un fichier, soit un dossier, utilisez ||. Cela rend l'intention plus explicite qu'une expression trop dense.

if [ -f "$path" ] || [ -d "$path" ]; then
  echo "Chemin gere par le script"
else
  echo "Type non supporte ou chemin absent" >&2
fi

Dans Bash, [[ ]] est souvent plus agreable, mais ne l'utilisez pas si le script doit tourner avec sh. La premiere ligne du script doit assumer ce choix.

#!/usr/bin/env bash

if [[ -f "$file" && -s "$file" ]]; then
  echo "Fichier present et non vide"
fi

Cette decision compte en entreprise. Un script lance sur une distribution minimale, un NAS, un conteneur ou une appliance peut ne pas avoir le meme shell par defaut. Portabilite ou confort Bash : choisissez consciemment.

Gerer les liens symboliques

Les liens symboliques meritent une attention particuliere. D'apres la documentation Bash, la plupart des tests suivent le lien et regardent la cible. En revanche, -L et -h testent le lien lui-meme. C'est important si votre script doit nettoyer, remplacer ou auditer des chemins.

if [ -L "$path" ]; then
  echo "Cest un lien symbolique"
fi

if [ -e "$path" ]; then
  echo "La cible existe"
fi

Un lien casse peut etre detecte comme lien avec -L, tout en echouant avec -e parce que sa cible n'existe plus. Ce cas arrive dans les deploiements, les releases versionnees ou les dossiers partages.

if [ -L "$path" ] && [ ! -e "$path" ]; then
  echo "Lien symbolique casse: $path" >&2
fi

Ne supprimez pas un lien symbolique comme si c'etait toujours un fichier ordinaire. Selon le contexte, il peut pointer vers une version active, un dossier partage ou une cible montee ailleurs. Le bon script distingue le lien et la cible.

Checklist

Checklist pour un test Bash robuste

Avant dautomatiser une operation fichier, controlez ces points.

  • ✓Choisir -f, -d ou -e selon laction suivante.
  • ✓Mettre les variables de chemin entre guillemets doubles.
  • ✓Tester les permissions avant lecture, ecriture ou execution.
  • ✓Utiliser && et || plutot que -a et -o dans test.
  • ✓Traiter les liens symboliques avec -L quand ils comptent.
  • ✓Retourner un message derreur clair sur stderr et un exit code utile.

Construire une fonction reutilisable

Quand le meme controle revient plusieurs fois, transformez-le en fonction. Le script devient plus lisible et les messages d'erreur restent coherents.

require_file() {
  local file="$1"

  if [ ! -f "$file" ]; then
    echo "Fichier requis absent: $file" >&2
    return 1
  fi

  if [ ! -r "$file" ]; then
    echo "Fichier non lisible: $file" >&2
    return 1
  fi
}

require_file "/etc/app/config.ini" || exit 1

Pour un dossier de sortie, la fonction peut verifier l'existence puis creer le dossier si c'est acceptable. Ne le faites pas silencieusement dans tous les cas : parfois, l'absence du dossier signifie que l'environnement est mal monte.

require_output_dir() {
  local dir="$1"

  mkdir -p "$dir" || return 1

  if [ ! -d "$dir" ] || [ ! -w "$dir" ]; then
    echo "Dossier de sortie inutilisable: $dir" >&2
    return 1
  fi
}

require_output_dir "/var/backups/app" || exit 1

La fonction rend le script plus professionnel : chaque verification a un nom, un message et un code de retour. C'est le niveau minimum pour une tache planifiee ou un deploiement repete.

Penser aux scripts lances par cron ou un service

Un test qui fonctionne dans votre terminal peut echouer quand le script tourne dans cron, dans un service systemd ou dans un conteneur. Le repertoire courant n'est pas toujours le meme, les variables d'environnement peuvent etre reduites et l'utilisateur d'execution peut avoir moins de droits. Dans ce contexte, les chemins relatifs deviennent une source d'erreurs.

Preferez les chemins absolus pour les fichiers critiques. Si vous devez partir du dossier du script, calculez-le explicitement, puis construisez vos chemins a partir de cette base.

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
config_file="$script_dir/config/app.ini"

if [ ! -f "$config_file" ]; then
  echo "Configuration introuvable: $config_file" >&2
  exit 1
fi

Cette approche evite un piege courant : lancer le script depuis un dossier different et chercher la configuration au mauvais endroit. Elle rend aussi les logs plus lisibles, car le message contient le chemin complet qui a echoue.

Sur un service, pensez aussi a verifier l'utilisateur reel. Un fichier peut etre lisible pour vous et illisible pour le compte qui lance la tache. Si le script doit ecrire dans un dossier, testez le droit avec ce compte, pas seulement avec votre session administrateur.

whoami
test -w "$output_dir" || {
  echo "Pas de droit ecriture sur $output_dir" >&2
  exit 1
}

Enfin, ne laissez pas les erreurs silencieuses. Activez une journalisation minimale ou retournez des messages explicites. Un script automatique doit permettre de comprendre rapidement si le probleme vient d'un fichier absent, d'un type incorrect, d'une permission ou d'un chemin calcule au mauvais endroit.

Erreurs frequentes a eviter

La premiere erreur est d'oublier les guillemets autour des variables. Elle ne se voit pas avec un chemin simple, puis casse le jour ou un dossier contient un espace. Dans un script, utilisez "$path" par defaut.

La deuxieme erreur est de tester l'existence avec -e alors que l'action attend un fichier ou un dossier precis. Le script devient moins strict que l'operation qu'il prepare. Cela produit des erreurs tardives.

La troisieme erreur est de melanger -a et -o dans des expressions longues. Les specifications POSIX recommandent des formes plus explicites avec && et ||. C'est plus lisible, et moins fragile face aux entrees inattendues.

La quatrieme erreur est de ne pas ecrire sur stderr en cas d'erreur. Un message d'echec doit aller vers >&2, surtout si la sortie standard est consommee par un autre programme.

echo "Erreur: fichier manquant" >&2
exit 1

La cinquieme erreur est de croire qu'un test remplace une gestion d'erreur. Entre le test et l'action, le fichier peut changer. Pour une operation critique, gardez un controle du code de retour de la commande qui agit vraiment. Tester ne suffit pas toujours.

Par exemple, verifier qu'un dossier existe avant une copie ne garantit pas que la copie reussira. Le disque peut etre plein, le dossier peut disparaitre, ou les droits peuvent changer. Le bon script teste avant, execute, puis controle le resultat de la commande.

if [ -d "$backup_dir" ] && [ -w "$backup_dir" ]; then
  cp "$file" "$backup_dir/" || {
    echo "Copie echouee vers $backup_dir" >&2
    exit 1
  }
fi

Cette double verification est particulierement utile pour les sauvegardes, les exports et les deploiements. Elle transforme une erreur tardive en signal exploitable et limite les etats partiels difficiles a comprendre.

Point important
Un test Bash valide un etat a un instant donne. Pour une operation critique, testez avant, puis controlez aussi le code de retour de la commande qui lit, ecrit, copie ou supprime.

La priorite a retenir

Pour detecter un fichier ou un dossier efficacement, gardez une regle simple : le test doit dire exactement ce que votre script attend. -f pour un fichier regulier, -d pour un dossier, -e seulement quand le type importe peu, et des tests de permissions avant toute action sensible.

Votre prochaine action : remplacez les tests vagues de vos scripts par des fonctions explicites. Une fonction require_file, une fonction require_output_dir, des variables quotees et des messages sur stderr suffisent deja a rendre vos automatisations nettement plus fiables.

Questions frequentes
Morgan
À propos de l'auteur Morgan

Depuis mon adolescence, je m'intéresse de près aux technologies de l'information, une curiosité qui m'a naturellement conduit à créer ma propre agence digitale. Cette ave…

À lire aussi

À lire ensuite

Recevez les actus gaming utiles

Un recap net, des sorties a surveiller et nos meilleurs debriefs sans spam.

Aucun spam. Désinscription en un clic.

Recevez les actus gaming utiles