Maîtrise de l'analyse des arguments Bash pour des scripts puissants
Analysez les arguments Bash avec des paramètres positionnels, getopts, des boucles pour les options longues, des valeurs par défaut et des messages d'erreur d'utilisation clairs.
Maîtrise de l'analyse des arguments Bash pour des scripts puissants
Les arguments en ligne de commande rendent vos scripts Bash flexibles. Lorsque l'analyse des arguments Bash est faible, vous finissez par modifier des variables à l'intérieur du script chaque fois que vous avez besoin d'un fichier, d'un hôte ou d'un mode différent.
Ce guide vous montre comment gérer les arguments positionnels, les options courtes avec getopts et les options longues avec une boucle while/case. L'objectif est un script qui rejette les mauvaises entrées tôt et vous indique exactement comment l'exécuter.
Les bases : les arguments positionnels
Avant d'aborder les drapeaux et les options nommées, il est crucial de comprendre comment Bash gère les arguments simples et séquentiels.
| Variable | Description | Exemple si appelé comme ./script.sh foo bar |
|---|---|---|
$0 |
Le nom du script lui-même | ./script.sh |
$1, $2, ... |
Le premier, deuxième, etc., argument positionnel | foo, bar |
$# |
Le nombre d'arguments positionnels | 2 |
$@ |
Tous les arguments positionnels, traités comme des chaînes séparées | foo bar |
$* |
Tous les arguments positionnels, traités comme une seule chaîne | foo bar |
Exemple : Vérification positionnelle simple
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Usage : $0 <fichier_source> <répertoire_destination>"
exit 1
fi
SOURCE="$1"
DESTINATION="$2"
echo "Copie de $SOURCE vers $DESTINATION..."
# cp "$SOURCE" "$DESTINATION"
Analyse standard avec getopts pour les options courtes
Pour les scripts professionnels nécessitant des options comme -v (verbose) ou -f <fichier>, l'utilitaire intégré getopts est la méthode canonique et la plus fiable en Bash pur. Il est conçu spécifiquement pour les options courtes (à un seul caractère).
Comment fonctionne getopts
getopts lit les options séquentiellement, en définissant la variable désignée (généralement OPT) sur l'option trouvée et en plaçant la valeur de tout argument (si nécessaire) dans la variable OPTARG.
- Chaîne d'options (OPTSTRING) : Définit les options valides. Si une option nécessite un argument (par exemple,
-f nomfichier), suivez le caractère par deux-points (:). Exemple :vho:permet-v,-h, et-oqui nécessite une valeur. OPTIND: Un index Bash interne qui suit le prochain argument à traiter. Il doit être initialisé à 1 (ce qui est la valeur par défaut, mais parfois réinitialisé dans des scripts complexes).
Modèle pratique getopts
Ce modèle gère trois options : -v (drapeau), -h (drapeau) et -f (option nécessitant une valeur).
#!/bin/bash
# --- Valeurs par défaut ---
VERBOSE=0
NOMFICHIER="fichier_par_defaut.txt"
# --- Fonction d'utilisation ---
usage() {
echo "Usage : $0 [-v] [-h] [-f <fichier>] <entrée>"
exit 1
}
# --- Boucle d'analyse des arguments ---
while getopts ":vhf:" OPT; do
case "$OPT" in
v)
VERBOSE=1
echo "Mode verbeux activé."
;;
h)
usage
;;
f)
# OPTARG contient l'argument fourni à -f
NOMFICHIER="$OPTARG"
echo "Nom du fichier de sortie défini sur : $NOMFICHIER"
;;
\?)
# Gère les options non reconnues
echo "Erreur : Option invalide -$OPTARG" >&2
usage
;;
:)
# Gère les arguments manquants pour les options qui en nécessitent un (par exemple, -f sans nom de fichier)
echo "Erreur : L'option -$OPTARG nécessite un argument." >&2
usage
;;
esac
done
# --- Décalage des arguments positionnels ---
# Une fois getopts terminé, OPTIND contient l'index du premier argument non optionnel.
# Nous utilisons shift pour supprimer toutes les options analysées, ne laissant que les arguments positionnels ($1, $2, etc.).
shift $((OPTIND - 1))
# Vérifier si l'argument positionnel requis (ENTRÉE) est présent
DONNÉES_ENTRÉE="$1"
if [ -z "$DONNÉES_ENTRÉE" ]; then
echo "Erreur : Données d'entrée requises."
usage
fi
echo "---"
echo "Traitement de l'entrée : $DONNÉES_ENTRÉE"
echo "Statut verbeux : $VERBOSE"
Astuce : Utilisez toujours
shift $((OPTIND - 1))immédiatement après la bouclewhile getoptspour séparer proprement les options des arguments positionnels restants.
Gestion des options longues comme --option
Le getopts intégré de Bash pur ne prend en charge que les options courtes. Pour gérer les options longues modernes (par exemple, --verbose, --output-file=data.log), vous devez implémenter une boucle d'analyse personnalisée en utilisant while et case avec la commande shift.
Cette méthode nécessite une gestion des arguments plus explicite.
Analyseur d'options longues personnalisé
#!/bin/bash
# --- Valeurs par défaut ---
VERBOSE=0
FICHIER_SORTIE=""
# Fonction personnalisée pour afficher l'utilisation (omise pour la brièveté)
# usage() { ... }
while [ "$#" -gt 0 ]; do
case "$1" in
--verbose)
VERBOSE=1
shift
;;
--output-file)
# Nécessite deux shifts : un pour le drapeau, un pour la valeur
if [ -z "${2:-}" ]; then
echo "Erreur : --output-file nécessite une valeur."
exit 1
fi
FICHIER_SORTIE="$2"
shift 2
;;
--help)
usage
;;
-*)
echo "Erreur : Option inconnue $1" >&2
exit 1
;;
*)
# Premier argument positionnel trouvé, arrêter l'analyse des options
break
;;
esac
done
# Les arguments restants sont maintenant disponibles sous forme de $1, $2, etc.
# ... La logique du script continue ...
if [ "$FICHIER_SORTIE" ]; then
echo "Données redirigées vers $FICHIER_SORTIE"
fi
Si votre script accepte des arguments positionnels après les options, continuez l'analyse jusqu'à ce que vous rencontriez -- ou le premier argument non optionnel. Une convention courante est de laisser -- signifier "arrêter l'analyse des options maintenant" :
while [ "$#" -gt 0 ]; do
case "$1" in
--)
shift
break
;;
--verbose)
VERBOSE=1
shift
;;
*)
break
;;
esac
done
Avancé : Gestion des options longues clé-valeur (--key=value)
Si vous préférez le style UNIX standard où les arguments sont passés à l'aide d'un signe égal, vous devez utiliser la substitution de paramètres pour diviser l'argument.
while [ "$#" -gt 0 ]; do
case "$1" in
--limit=*)
VALEUR_LIMITE="${1#*=}" # Supprime tout jusqu'au '=' inclus
echo "Limite définie sur : $VALEUR_LIMITE"
shift
;;
# ... autres options ...
esac
done
Meilleures pratiques pour des scripts robustes
A. Combinaison d'options courtes et longues
Pour une flexibilité maximale, les scripteurs expérimentés combinent souvent la fiabilité de getopts pour les options courtes avec la boucle while/case personnalisée pour les options longues. La boucle d'options longues s'exécute en premier, consommant les drapeaux longs, puis les arguments restants (y compris les options courtes) sont traités par getopts.
Cependant, un modèle plus propre et courant consiste à traiter tous les arguments dans une boucle personnalisée robuste qui recherche à la fois -o et --option, en effectuant les shifts appropriés.
B. Gestion des erreurs et utilisation
Fournissez toujours une fonction usage claire qui explique les arguments et options requis du script. Cette fonction doit être appelée lorsque :
- L'utilisateur demande de l'aide (par exemple,
-hou--help). - Un argument requis est manquant.
- Une option invalide ou inconnue est fournie.
Assurez-vous que le script se termine avec un statut non nul en cas d'erreur (exit 1) et envoie les messages d'erreur sur la sortie d'erreur standard (>&2).
C. Valeurs par défaut
Initialisez toutes les variables de configuration au début du script avec des valeurs par défaut sensées. Cela rend votre script prévisible même si aucun argument optionnel n'est passé.
# Toujours initialiser les variables avant l'analyse
NIVEAU_LOG="info"
FORCE=0
À retenir
Utilisez les arguments positionnels pour les valeurs requises simples, getopts pour les options courtes portables, et une boucle while/case personnalisée lorsque vous avez besoin d'options longues. Testez les valeurs manquantes, les drapeaux inconnus et les arguments avec des espaces avant de faire confiance au script dans l'automatisation.