Objectifs
- Structurer un script Bash complexe en utilisant des fonctions.
- Créer un squelette de script réutilisable qui inclut :
- Le “mode strict” (
set -euo pipefail). - Le parsing d’arguments avec
getopts. - Une fonction d’aide (
usage). - Une fonction pour gérer les erreurs.
- Une fonction
maincomme point d’entrée.
- Le “mode strict” (
Explications détaillées
Notions clés
Lorsque vos scripts dépassent quelques dizaines de lignes, il devient essentiel de leur donner une structure pour qu’ils restent lisibles, maintenables et robustes. Ce “squelette” est une convention que vous pouvez réutiliser pour presque tous les outils en ligne de commande que vous écrirez.
La structure d’un script robuste
- Shebang et
set: La base de la sécurité et de la prévisibilité. - Documentation : Un bloc de commentaires en haut qui explique le but du script, son usage et les options qu’il accepte.
- Fonctions utilitaires : Des petites fonctions pour les tâches répétitives, comme afficher l’aide (
usage()) ou mourir proprement sur une erreur (die()). - Parsing des arguments : Un bloc
while getoptspour gérer les options. - La fonction
main(): Le cœur de la logique du script. Cette convention permet de lire le script de haut en bas : on voit d’abord la configuration et les fonctions, puis le point d’entrée principal tout à la fin.
Le squelette de script
Voici un squelette complet et commenté que vous pouvez utiliser comme point de départ pour vos propres projets.
#!/usr/bin/env bash
# Active le mode strict pour des scripts plus sûrs
set -euo pipefail
# --- Documentation et Constantes ---
# Description:
# Ce script est un squelette pour un outil en ligne de commande robuste.
#
# Usage:
# ./mon_outil.sh [-v] [-f <fichier>] <argument_obligatoire>
#
# Options:
# -v Active le mode verbeux.
# -f <fichier> Spécifie un fichier de sortie.
#
readonly SCRIPT_NAME="$(basename "$0")"
# --- Fonctions ---
# Affiche un message d'erreur et quitte
die() {
echo >&2 "[ERREUR] $@"
exit 1
}
# Affiche l'aide du script
usage() {
echo "Usage: $SCRIPT_NAME [-v] [-f <fichier>] <argument_obligatoire>"
echo ""
echo "Options:"
echo " -v Active le mode verbeux"
echo " -f <fichier> Spécifie un fichier de sortie"
echo " -h Affiche cette aide"
exit 0
}
# Fonction principale contenant la logique du script
main() {
# --- Initialisation et parsing des arguments ---
local VERBOSE=false
local OUTPUT_FILE=""
while getopts ":hvf:" opt; do
case "$opt" in
h) usage ;;
v) VERBOSE=true ;;
f) OUTPUT_FILE="$OPTARG" ;;
\?|:) die "Option invalide ou argument manquant. Utilisez -h pour l'aide." ;;
esac
done
shift $((OPTIND - 1)) # Supprime les options parsées
# --- Validation des arguments restants ---
if [[ $# -ne 1 ]]; then
usage
fi
local ARG_OBLIGATOIRE="$1"
# --- Logique principale du script ---
if [[ "$VERBOSE" == true ]]; then
echo "Mode verbeux activé."
fi
echo "Argument obligatoire : $ARG_OBLIGATOIRE"
if [[ -n "$OUTPUT_FILE" ]]; then
echo "La sortie sera dans : $OUTPUT_FILE"
# echo "Contenu..." > "$OUTPUT_FILE"
else
echo "Sortie sur stdout."
# echo "Contenu..."
fi
echo "Script terminé avec succès."
}
# --- Point d'entrée ---
# On appelle la fonction main avec tous les arguments du script
main "$@"
Bonnes pratiques
- Découpez votre logique en fonctions. Chaque fonction doit avoir une seule responsabilité.
- Utilisez une fonction
main. Cela rend le point de départ de votre script explicite. - Gérez les erreurs gracieusement. Utilisez une fonction
dieouerrorpour afficher des messages clairs surstderret quitter avec un code d’erreur.
Pièges courants
- Mettre tout le code au niveau global. Sans fonctions, un script devient vite un plat de spaghettis illisible dès qu’il dépasse une vingtaine de lignes.
- Ne pas valider les arguments. Un script qui fait confiance à ses arguments est un script qui plantera de manière inattendue.
Exercices
-
Adoptez le squelette :
- Copiez-collez le squelette ci-dessus dans un nouveau fichier
mon_outil.shet rendez-le exécutable. - Lancez-le de plusieurs manières pour voir comment il se comporte :
./mon_outil.sh -h./mon_outil.sh(sans arguments)./mon_outil.sh -v -f sortie.txt mon_argument./mon_outil.sh -x(option invalide)
- Copiez-collez le squelette ci-dessus dans un nouveau fichier
-
Créez un outil de “listing” :
- Adaptez le squelette pour créer un script
lister.sh. - L’argument obligatoire est un chemin de dossier.
- Ajoutez une option
-apour “all”, qui passera l’option-aà la commandels -l. - La logique dans
maindoit simplement exécuterls -l(ouls -lasi-aest présent) sur le dossier fourni.
- Adaptez le squelette pour créer un script
-
Ajoutez une validation :
- Modifiez
lister.shpour qu’il vérifie si l’argument est bien un dossier qui existe ([[ -d ... ]]). - S’il n’existe pas, appelez la fonction
dieavec un message d’erreur approprié.
- Modifiez