-f
Vrai si le chemin existe et correspond a un fichier regulier.
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.
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.
Ces primaires couvrent la plupart des scripts de maintenance, sauvegarde ou deploiement.
Vrai si le chemin existe et correspond a un fichier regulier.
Vrai si le chemin existe et correspond a un repertoire.
Vrai si le chemin existe, quel que soit son type.
Vrai si le fichier existe et nest pas vide.
Verifie lecture, ecriture ou execution selon lutilisateur courant.
Vrai si le chemin est un lien symbolique.
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. |
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.
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.
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 eviter
Preferer && et || pour composer les tests de facon plus lisible et moins ambigue.
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.
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.
Avant dautomatiser une operation fichier, controlez ces points.
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.
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.
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.
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.
À lire aussi
Un recap net, des sorties a surveiller et nos meilleurs debriefs sans spam.
Aucun spam. Désinscription en un clic.