Tutoriel Linux

Getopts en Bash : accepter -f, -v et -h sans parser les arguments à la main

Débutant4 min de lecture

Un script Bash devient vite pénible quand il faut gérer plusieurs options, un fichier obligatoire et une aide lisible. Avec getopts, vous pouvez traiter proprement -f, -v et -h sans bricoler une boucle qui découpe les arguments à la main.

Le point utile est ailleurs qu’une simple lecture des options : getopts vous donne aussi OPTARG pour récupérer la valeur d’une option et OPTIND pour savoir où commencent les arguments positionnels. Le script peut donc refuser une option inconnue, signaler un argument manquant et vérifier ses paramètres avant de faire quoi que ce soit.

La structure minimale avec getopts

Voici un script complet. Il attend un fichier avec -f, active un mode verbeux avec -v et affiche son aide avec -h :

#!/usr/bin/env bash
set -u

usage() {
  printf 'Usage: %s -f fichier [-v] [-h]n' "$0" >&2
}

verbose=0
file=''

while getopts ':f:vh' opt; do
  case "$opt" in
    f) file=$OPTARG ;;
    v) verbose=1 ;;
    h) usage; exit 0 ;;
    :) printf 'Option -%s requiert un argument.n' "$OPTARG" >&2; usage; exit 2 ;;
    ?) printf 'Option inconnue : -%sn' "$OPTARG" >&2; usage; exit 2 ;;
  esac
done

shift "$((OPTIND - 1))"

if [ -z "$file" ] || [ "$#" -ne 0 ]; then
  usage
  exit 2
fi

printf 'Fichier : %sn' "$file"
printf 'Mode verbeux : %sn' "$verbose"

La chaîne passée à getopts est :f:vh. Le deux-points placé au début active la gestion silencieuse des erreurs. Ensuite, f: signifie que -f attend une valeur, tandis que v et h sont des options sans argument.

Comprendre OPTARG et OPTIND

Quand le script rencontre -f config.yml, Bash place config.yml dans OPTARG. La branche f) copie donc cette valeur dans la variable file. Il ne faut pas lire directement l’argument suivant avec $2 ou $3 : cela casse dès que l’utilisateur inverse l’ordre des options ou les regroupe.

OPTIND contient la position du prochain argument à traiter. Après la boucle, shift "$((OPTIND - 1))" retire les options déjà consommées. Il ne reste alors que les arguments positionnels. Dans cet exemple, le test [ "$#" -ne 0 ] refuse les paramètres supplémentaires au lieu de les ignorer.

Le manuel Bash décrit getopts dans la partie consacrée aux builtins du shell : documentation officielle Bash.

Gérer les erreurs sans ambiguïté

Les deux branches les plus importantes sont :) et ? :

  • :) est appelée quand une option attendue n’a pas reçu sa valeur, par exemple ./script.sh -f. Le caractère de l’option concernée est disponible dans OPTARG.
  • ? est appelée quand l’utilisateur fournit une option qui n’existe pas, par exemple -x. Là encore, OPTARG contient le caractère reçu.

Le code de sortie 2 permet à un autre script ou à un outil d’automatisation de distinguer une erreur d’utilisation d’une exécution réussie. L’aide sort sur la sortie d’erreur, ce qui évite de mélanger le mode normal et les messages de diagnostic.

Tester plusieurs formes d’appel

Une fois le fichier enregistré, rendez-le exécutable :

chmod +x script.sh

./script.sh -f config.yml
./script.sh -v -f config.yml
./script.sh -fconfig.yml
./script.sh -h
./script.sh -x
./script.sh -f

Les deux premiers appels doivent afficher le fichier et l’état du mode verbeux. -fconfig.yml est aussi accepté par getopts. Les trois derniers cas doivent afficher une aide et retourner un code différent de zéro, sauf pour -h qui doit se terminer avec le code 0.

Avant de brancher ce parseur sur une action sensible, vérifiez aussi la syntaxe :

bash -n script.sh

Vous pouvez ensuite faire relire le script par ShellCheck si l’outil est installé sur votre machine. Pour les arguments positionnels et la manipulation des chemins, le guide sur basename et dirname dans Bash complète bien ce cas. Si votre script parcourt une liste ou un fichier ligne par ligne, le guide sur la boucle while en Bash traite l’autre partie du problème.

Ce qu’il faut vérifier avant d’aller plus loin

Gardez la validation des options avant toute suppression, copie, connexion distante ou modification de configuration. Une option obligatoire absente doit arrêter le script immédiatement. Si le fichier passé avec -f doit exister, ajoutez ensuite un contrôle comme [ -f "$file" ] et affichez une erreur précise.

getopts ne remplace pas la validation métier : il organise les arguments, mais ne sait pas si un chemin est lisible, si un port est valide ou si un utilisateur a les droits nécessaires. C’est cette séparation qui rend le script plus simple à tester et à maintenir.

Illustration Linux d’un script Bash qui reçoit et vérifie plusieurs options
Un script Bash vérifie ses options avant d’exécuter une action.