KYOSH1RO

◀ Documentation

Écrire un script Bash : le mémo pour scripter

Bash · Shell · Scripting · Linux · +1 | 📅 Mis à jour : 21/08/2026 | ⏱ ~8 min de lecture
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.
#!/bin/bash
Forme plus portable, recommandée aujourd'hui — elle trouve Bash où qu'il soit installé (utile sur les BSD, macOS, etc.) :
#!/usr/bin/env bash
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) # substitution de commande avec $()
On peut forcer le type d'une variable avec declare :
declare -r constante="ne changera pas" # -r : lecture seule
declare -i entier=42 # -i : entier
declare -a tableau # -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" # sans accolades, Bash chercherait la variable a_suffixe
echo ${#a} # longueur de la variable (26 ici)
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} # si choix est vide/absent, vaut "N" ; sinon inchangé
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} # 6 caractères à partir du début -> abcdef
echo ${a:0:-4} # tout sauf les 4 derniers caractères
echo ${a/e/E} # remplace le premier "e" par "E"
echo ${a//e/E} # remplace TOUS les "e" (comme le /g de sed)
echo ${a^^} # tout en MAJUSCULES
echo ${a,,} # tout en minuscules
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 # -s masque la saisie
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 # $2 devient $1
echo "Nouveau premier : $1"
VI — Les calculs
L'arithmétique entière se fait entre doubles parenthèses $(( )) :
echo $((21 + 21)) # 42
echo $((63 - 21)) # 42
echo $((2 * 21)) # 42
echo $((84 / 2)) # 42
i=42
echo $(($i * 2)) # 84
resultat=$((i % 10)) # modulo (reste de la division) -> 2
Pour incrémenter ou décrémenter :
i=42
((i++)) # i vaut 43
((i--)) # i vaut 42
let i+=10 # i vaut 52
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" ]] # a égal à b
if [[ "$a" -gt "$b" ]] # a plus grand que 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" ]] # chaînes identiques
if [[ -z "$var" ]] # variable vide ou non définie
if [[ -n "$var" ]] # variable renseignée
if [[ "$a" =~ ^a ]] # commence par un "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 ]] # est-ce un fichier ?
if [[ -d "$dossier" ]] # est-ce un répertoire ?
if [[ -e /tmp/verrou ]] # existe-t-il ?
Négation, ET, OU
Le ! inverse un test ; && est le ET, || est le OU :
if [[ ! -d "$dossier" ]] # si le dossier N'existe PAS
if [[ "$a" -gt 0 && "$b" -gt 0 ]] # les deux conditions
if [[ "$a" -eq 1 || "$a" -eq 2 ]] # l'une OU l'autre
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) # de 1 à 5
do
echo $i
done
for fichier in *.log # tous les .log du dossier courant
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" ;; # cas par défaut
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]} # premier élément (l'index commence à 0)
echo ${tab[2]} # troisième élément
echo ${tab[*]} # tous les éléments
echo ${#tab[*]} # nombre d'éléments
tab[0]=nouvelle # modifier un élément
tab+=("ajout") # ajouter à la fin
unset tab[1] # supprimer un élément
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 # -> Bonjour Patrick, tu as 30 ans.
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.
#!/usr/bin/env bash
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"; }
# On attend le dossier à sauvegarder en argument
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