Un script Bash, c'est simplement une suite de commandes shell écrites dans un fichier, qu'on exécute d'un coup au lieu de les taper une par une. Ce guide sert de mémo : on y trouve la syntaxe essentielle pour scripter — variables, tests, boucles, fonctions — avec des exemples directement réutilisables.
I — Le squelette d'un script
Tout script Bash commence par un shebang : la première ligne, qui indique au système quel interpréteur utiliser.
Forme plus portable, recommandée aujourd'hui — elle trouve Bash où qu'il soit installé (utile sur les BSD, macOS, etc.) :
Une fois le script écrit, il faut le rendre exécutable avant de le lancer :
chmod +x mon_script.sh
./mon_script.sh
II — Développer proprement dès le départ
À placer juste après le shebang. Ces trois options transforment Bash en interpréteur strict et vous évitent des heures de débogage :
set -euo pipefail
-e arrête le script dès qu'une commande échoue (code de retour non nul)
-u variable non définie = erreur, au lieu de la remplacer par du vide
-o pipefail dans un pipeline (cmd1 | cmd2), échoue si une commande échoue, pas juste la dernière
Prenez l'habitude de le mettre systématiquement. Sans -u, une faute de frappe dans un nom de variable passe inaperçue et peut faire des dégâts (un rm dans un dossier vide, par exemple).
III — Les variables
Affectation
Pas d'espace autour du signe =. Une chaîne, un nombre, ou le résultat d'une commande :
a="abcdefghijklmnopqrstuvwxyz"
b=2
nb=$(ls -l /etc | wc -l)
On peut forcer le type d'une variable avec declare :
declare -r constante="ne changera pas"
declare -i entier=42
declare -a tableau
Utiliser une variable
On préfixe le nom par $. Les accolades ${...} lèvent toute ambiguïté (indispensable quand le nom est collé à autre chose) :
echo $a
echo ${a}
echo "${a}_suffixe"
echo ${#a}
Valeur par défaut
Pratique pour un choix optionnel : si la variable est vide ou non définie, elle prend la valeur de repli.
choix=${choix:-N}
Manipulation de chaînes
Bash sait découper et transformer une chaîne sans appeler sed ou cut (la première position est 0) :
echo ${a:0:6}
echo ${a:0:-4}
echo ${a/e/E}
echo ${a//e/E}
echo ${a^^}
echo ${a,,}
IV — Lire une saisie clavier
La commande read récupère ce que tape l'utilisateur dans une variable. L'option -p affiche un message d'invite (non inclus dans la réponse) :
read -p "Saisir un mot : " texte
echo "Vous avez tapé : $texte"
read -s -p "Mot de passe : " mdp
V — Arguments et variables spéciales
Quand on appelle un script avec des paramètres (./script.sh fichier1 fichier2), Bash les expose via des variables numérotées :
● $0 : nom du script
● $1, $2, $3... : premier, deuxième, troisième argument
● $# : nombre total d'arguments
● $@ : tous les arguments (à mettre entre guillemets : "$@")
● ${!#} : le dernier argument
D'autres variables spéciales servent au contrôle d'exécution :
● $? : code de retour de la dernière commande (0 = succès)
● $$ : PID du script en cours
● $! : PID de la dernière commande lancée en arrière-plan
● $RANDOM : entier aléatoire entre 0 et 32767
● $EUID : identifiant de l'utilisateur (0 = root)
shift : décaler les arguments
shift supprime $1 et décale tous les autres d'un cran ($2 devient $1, etc.). Idéal pour traiter les arguments un par un dans une boucle :
echo "Premier argument : $1"
shift
echo "Nouveau premier : $1"
VI — Les calculs
L'arithmétique entière se fait entre doubles parenthèses $(( )) :
echo $((21 + 21))
echo $((63 - 21))
echo $((2 * 21))
echo $((84 / 2))
i=42
echo $(($i * 2))
resultat=$((i % 10))
Pour incrémenter ou décrémenter :
i=42
((i++))
((i--))
let i+=10
VII — Les conditions : if
La structure de base d'un test :
if [[ condition ]]
then
commande1
commande2
fi
Avec les branches else et elif :
if [[ "$age" -lt 18 ]]
then
echo "Mineur"
elif [[ "$age" -lt 65 ]]
then
echo "Adulte"
else
echo "Senior"
fi
En Bash on écrit les tests entre doubles crochets [[ ... ]] plutôt que simples [ ... ]. Le double crochet est plus sûr (pas de souci avec les variables vides) et gère les regex ainsi que && et ||. Prenez l'habitude d'utiliser [[ ... ]].
VIII — Les opérateurs de comparaison
Comparaison d'entiers
-eq égal à
-ne différent de
-gt strictement plus grand
-ge plus grand ou égal
-lt strictement plus petit
-le plus petit ou égal
if [[ "$a" -eq "$b" ]]
if [[ "$a" -gt "$b" ]]
Comparaison de chaînes
== égal à
!= différent de
-z vrai si la chaîne est vide (longueur 0)
-n vrai si la chaîne n'est pas vide
=~ correspond à une expression régulière
if [[ "$a" == "$b" ]]
if [[ -z "$var" ]]
if [[ -n "$var" ]]
if [[ "$a" =~ ^a ]]
Tests sur les fichiers
-e le fichier existe
-f existe et c'est un fichier ordinaire
-d existe et c'est un répertoire
-h existe et c'est un lien symbolique
-r lisible -w modifiable -x exécutable
-s existe et n'est pas vide
if [[ -f /etc/passwd ]]
if [[ -d "$dossier" ]]
if [[ -e /tmp/verrou ]]
Négation, ET, OU
Le ! inverse un test ; && est le ET, || est le OU :
if [[ ! -d "$dossier" ]]
if [[ "$a" -gt 0 && "$b" -gt 0 ]]
if [[ "$a" -eq 1 || "$a" -eq 2 ]]
IX — Les boucles
for
for i in 1 2 3 4 5
do
echo "Tour numéro $i"
done
Sur une liste générée, ou sur des fichiers :
for i in $(seq 1 5)
do
echo $i
done
for fichier in *.log
do
echo "Traitement de $fichier"
done
while
Répète tant que la condition est vraie :
x=1
while [[ "$x" -le 5 ]]
do
echo "Passage $x"
x=$((x + 1))
done
Boucle infinie qu'on interrompt avec break :
while :
do
read -p "Un chiffre (-1 pour quitter) : " a
if [[ "$a" -eq -1 ]]
then
break
fi
echo "Saisi : $a"
done
break sort de la boucle, continue passe directement au tour suivant.
case (aiguillage)
Le case remplace une longue série de if/elif quand on teste une même variable contre plusieurs valeurs :
case "$unite" in
B) echo "Octet" ;;
KB) echo "KiloOctet" ;;
MB) echo "MegaOctet" ;;
GB) echo "GigaOctet" ;;
*) echo "Unité inconnue" ;;
esac
X — Les tableaux
L'espace sépare les éléments ; les guillemets protègent une valeur qui en contient un :
tab=(val1 val2 val3 "val 4 avec espaces")
echo ${tab[0]}
echo ${tab[2]}
echo ${tab[*]}
echo ${#tab[*]}
tab[0]=nouvelle
tab+=("ajout")
unset tab[1]
Parcourir un tableau avec une boucle for :
for element in "${tab[@]}"
do
echo "-> $element"
done
XI — Les fonctions
Une fonction regroupe des commandes réutilisables. On la déclare, puis on l'appelle par son nom. Les arguments se récupèrent avec $1, $2... comme pour le script :
saluer() {
echo "Bonjour $1, tu as $2 ans."
}
saluer "Patrick" 30
Déclarez vos fonctions AVANT de les appeler : Bash lit le script de haut en bas.
XII — Astuces utiles
Lire un fichier ligne par ligne
while read ligne
do
echo "$ligne"
done < fichier.txt
Avec un séparateur (ici le : de /etc/passwd), on répartit directement dans plusieurs variables :
while IFS=: read user pass uid gid nom home shell
do
echo "$user (UID $uid) -> $home"
done < /etc/passwd
Vérifier qu'on est root
if [[ $EUID -ne 0 ]]
then
echo "Ce script doit être lancé en root."
exit 1
fi
Vérifier le succès d'une commande
Chaque commande renvoie un code de retour dans $? (0 = succès). Le plus lisible est de tester la commande directement :
if ! mkdir /tmp/sauvegarde
then
echo "Échec de la création du dossier"
exit 1
fi
Mettre du texte en couleur
ROUGE='\033[0;31m'
VERT='\033[0;32m'
RESET='\033[0m'
echo -e "${VERT}OK${RESET} : tout est en ordre"
echo -e "${ROUGE}ERREUR${RESET} : quelque chose a échoué"
L'option -e de echo est indispensable pour que les codes couleur soient interprétés.
XIII — Un exemple complet
Un petit script de sauvegarde qui réunit la plupart des notions vues ci-dessus : options strictes, arguments, tests, fonction, code de retour et couleurs.
set -euo pipefail
VERT='\033[0;32m'
ROUGE='\033[0;31m'
RESET='\033[0m'
log_ok() { echo -e "${VERT}[OK]${RESET} $1"; }
log_err() { echo -e "${ROUGE}[ERREUR]${RESET} $1"; }
if [[ $# -ne 1 ]]
then
echo "Usage : $0 <dossier>"
exit 1
fi
source="$1"
if [[ ! -d "$source" ]]
then
log_err "Le dossier $source n'existe pas."
exit 1
fi
archive="sauvegarde_$(date +%Y%m%d).tar.gz"
if tar -czf "$archive" "$source"
then
log_ok "Archive créée : $archive"
else
log_err "La sauvegarde a échoué."
exit 1
fi