On lance un script, le terminal crache une erreur cryptique, et on passe vingt minutes à chercher un bug qui tient à un espace mal placé. Ce scénario revient en boucle quand on débute avec le shell. Les erreurs les plus courantes ne viennent pas d’une mauvaise logique, mais de pièges liés à la syntaxe du shell et au contexte d’exécution. Cet article cible les fautes concrètes qu’on rencontre dès les premiers scripts, avec les réflexes pour les éviter.
Espaces autour du signe égal : l’erreur shell la plus répandue
Quand on écrit i = 5 dans un script, le shell ne voit pas une affectation de variable. Il interprète i comme une commande à exécuter, et = et 5 comme ses arguments. Le message d’erreur typique est i: command not found.
La règle est stricte : aucune espace autour du signe égal lors d’une affectation. On écrit i=5, nom="fichier.txt", sans dérogation. L’inverse est vrai pour les tests : dans [ $i -le 5 ], les espaces autour des crochets et de l’opérateur sont obligatoires.
Ce piège attrape tout le monde parce que la plupart des langages de programmation acceptent (ou imposent) des espaces autour de =. En shell, la syntaxe d’affectation et la syntaxe de commande se distinguent uniquement par la présence ou l’absence d’espaces. Un réflexe simple : chaque fois qu’on affecte une variable, coller le nom, le = et la valeur sans aucun blanc.

Variables sans guillemets : des bugs invisibles dans vos scripts shell
On déclare une variable contenant un chemin de fichier avec des espaces, puis on l’utilise sans guillemets. Le shell découpe la valeur à chaque espace et passe plusieurs arguments là où on en attendait un seul.
Prenons un cas concret :
fichier="mon rapport.txt" suivi de cat $fichier. Le shell exécute cat mon rapport.txt, cherche deux fichiers distincts (« mon » et « rapport.txt »), et échoue. La correction tient en deux caractères : cat "$fichier".
- Toujours entourer
$variablede guillemets doubles, sauf quand on veut explicitement le découpage en mots (cas rare pour un débutant) - Tester ses scripts avec des noms de fichier contenant des espaces, c’est le moyen le plus rapide de détecter un guillemet manquant
- La syntaxe
"$variable"protège aussi contre les problèmes liés aux caractères spéciaux et aux lignes vides
L’oubli de guillemets est la source numéro un de comportements imprévisibles dans les scripts de débutants. On ne le voit pas tant qu’on travaille avec des noms de fichier simples, puis tout casse le jour où un répertoire contient un espace.
Shebang absent ou mauvais shell : quand le script ne tourne pas comme prévu
Un script qui fonctionne dans le terminal mais plante quand on le lance via cron ou dans un pipeline CI/CD, c’est souvent un problème de contexte d’exécution. Le premier réflexe à vérifier : la ligne shebang.
Sans #!/bin/bash en première ligne, le système utilise le shell par défaut, qui peut être sh, dash ou autre chose selon la distribution. Les syntaxes spécifiques à Bash (tableaux, [[ ]], substitution de processus) échouent silencieusement ou avec des erreurs obscures quand elles sont interprétées par un shell POSIX strict.
Le piège des environnements minimalistes
Dans un conteneur Docker minimal ou une tâche cron, la variable PATH est souvent réduite au strict minimum. Une commande comme grep ou echo peut ne pas être trouvée si le script s’appuie sur un PATH enrichi par le profil utilisateur. Déclarer le PATH en début de script évite ce genre de surprise.
Sur macOS, Bash reste en version 3.2 pour des raisons de licence. Un script écrit avec des fonctionnalités Bash 4+ (tableaux associatifs, par exemple) plante sans explication claire sur ce système. Les retours varient sur ce point selon les environnements, mais vérifier la version avec bash --version avant de déboguer une syntaxe qui semble correcte fait gagner du temps.
Gestion d’erreurs en shell : pourquoi set -e ne suffit pas
On lit souvent le conseil d’ajouter set -e en haut de ses scripts pour que l’exécution s’arrête à la première erreur. Le problème : set -e a des comportements surprenants dans plusieurs cas courants.
Une commande qui échoue à l’intérieur d’une condition if ne déclenche pas l’arrêt. Un échec dans un pipeline ne l’active pas non plus par défaut : seul le code de sortie de la dernière commande du pipe est pris en compte. On peut donc avoir grep motif fichier.txt | sort où grep échoue mais le script continue parce que sort a renvoyé un code de sortie à zéro.
La combinaison à adopter dès le départ
Pour une protection plus fiable, on combine trois options :
set -epour arrêter le script à la première erreur non géréeset -o pipefailpour que le code de sortie d’un pipeline reflète l’échec de n’importe quelle commande du pipe, pas seulement la dernièreset -upour que l’utilisation d’une variable non définie provoque une erreur au lieu de retourner une chaîne vide
POSIX.1-2024 a intégré set -o pipefail, ce qui renforce sa légitimité dans les scripts portables. Commencer chaque script par set -euo pipefail est un filet de sécurité que les débutants devraient adopter d’emblée.

Construire des commandes dynamiques avec eval : un réflexe à perdre
Quand on débute, on est tenté de construire une ligne de commande dans une variable puis de l’exécuter avec eval. Quelque chose comme cmd="ls -l $repertoire" suivi de eval $cmd. Ça fonctionne dans les cas simples, mais c’est un vecteur d’injection dès que la variable contient une entrée externe.
Si $repertoire vaut "; rm -rf /", le shell exécute la commande destructrice sans broncher. Appeler les commandes directement plutôt que via eval élimine ce risque. Quand on a besoin de flexibilité, on passe par des tableaux Bash pour stocker les arguments, ou on valide les entrées par liste blanche avant usage.
Le réflexe à construire : chaque fois qu’on se retrouve à concaténer des chaînes pour former une commande, s’arrêter et chercher une alternative. Les tableaux (args=("-l" "$repertoire") puis ls "${args[@]}") rendent le code lisible et sûr sans effort supplémentaire.
La majorité des erreurs shell tiennent à une poignée de pièges récurrents : espaces d’affectation, guillemets manquants, shebang oublié, gestion d’erreurs incomplète, eval mal maîtrisé. Les corriger ne demande pas de compétences avancées, mais de la rigueur sur ces quelques points précis. Un script court qui respecte ces règles de base sera plus fiable qu’un script long truffé de logique métier mais négligent sur la syntaxe.

