Débutant

Bash : maîtriser $0, $1, "$@" et getopts

Apprenez à utiliser les paramètres positionnels Bash, "$@" et getopts pour écrire des scripts clairs avec options et arguments sans ambiguïté.

Bash : maîtriser $0, $1, \
Difficulté
Facile

Les scripts Bash deviennent vite difficiles à maintenir quand les options et les arguments sont traités de façon approximative. Ce tutoriel vous guide pas à pas pour utiliser les paramètres positionnels et getopts de manière nette, lisible et sans ambiguïté.

Vous allez écrire de petits scripts concrets, puis les faire évoluer vers une interface en ligne de commande plus propre. L’objectif n’est pas de mémoriser une théorie abstraite, mais d’acquérir des gestes fiables que vous pourrez réutiliser partout.

Prérequis

Il faut disposer d’un shell Bash et savoir lancer un script depuis un terminal. Une connaissance minimale de chmod +x, des variables et des conditions en shell est utile, sans être indispensable.

Les exemples supposent un fichier de script créé dans un dossier de travail. Vous pouvez aussi les exécuter avec bash script.sh ... sans rendre le fichier exécutable.

Matériel nécessaire

  • Un terminal avec Bash
  • Un éditeur de texte
  • Un fichier de script de test

Étapes

  1. Créer un script minimal pour afficher les paramètres

    Créez un fichier demo.sh avec ce contenu :

    #!/usr/bin/env bash
    
    echo "0 = [$0]"
    echo "1 = [$1]"
    echo "2 = [$2]"
    echo "# = [$#]"

    Exécutez ensuite le script avec quelques arguments, par exemple bash demo.sh alpha beta. Observez que $0 désigne le nom utilisé pour invoquer le script, que $1 et $2 contiennent les premiers arguments, et que $# donne leur nombre.

  2. Lancer le script avec des arguments contenant des espaces

    Exécution d’un script dans un terminal avec plusieurs arguments, dont un argument entouré de guillemets pour conserver des espaces.

    Relancez le même script avec des arguments qui contiennent des espaces, par exemple bash demo.sh "un mot" "deux mots". Vérifiez que Bash conserve chaque argument cité comme une unité distincte.

    Modifiez ensuite le script pour afficher aussi tous les arguments d’un coup :

    #!/usr/bin/env bash
    
    echo "0 = [$0]"
    echo "1 = [$1]"
    echo "2 = [$2]"
    echo "# = [$#]"
    echo "@ = [$@]"
    echo "* = [$*]"
  3. Comparer "$@" et "$*" dans une boucle

    Remplacez le contenu du script par cette version :

    #!/usr/bin/env bash
    
    printf 'Boucle sur "$@"\n'
    for arg in "$@"; do
      printf '> [%s]\n' "$arg"
    done
    
    printf '\nBoucle sur "$*"\n'
    for arg in "$*"; do
      printf '> [%s]\n' "$arg"
    done

    Exécutez-le avec bash demo.sh "un mot" "deux mots" trois. Vous verrez que "$@" transmet chaque argument séparément, tandis que "$*" regroupe l’ensemble en une seule chaîne dans ce contexte.

  4. Afficher une aide quand aucun argument n’est fourni

    Faites évoluer le script pour guider l’utilisateur au lieu d’échouer silencieusement :

    #!/usr/bin/env bash
    
    usage() {
      echo "Usage: $0 NOM [AUTRE_ARGUMENT]"
    }
    
    if [ "$#" -eq 0 ]; then
      usage
      exit 1
    fi
    
    echo "Premier argument : [$1]"

    Testez d’abord sans argument, puis avec bash demo.sh Alice. Vous mettez ainsi en place une structure simple et réutilisable pour les scripts suivants.

  5. Décaler les paramètres avec shift

    Créez maintenant un script qui consomme le premier argument, puis continue avec les suivants :

    #!/usr/bin/env bash
    
    while [ "$#" -gt 0 ]; do
      echo "Argument courant : [$1]"
      shift
    done

    Lancez-le avec trois ou quatre arguments. À chaque itération, shift supprime le premier paramètre positionnel et décale les suivants vers la gauche.

  6. Accepter une option simple avant un argument

    Écrivez un premier script avec une option courte traitée manuellement :

    #!/usr/bin/env bash
    
    bonjour=false
    
    if [ "$1" = "-b" ]; then
      bonjour=true
      shift
    fi
    
    if [ "$#" -eq 0 ]; then
      echo "Usage: $0 [-b] NOM"
      exit 1
    fi
    
    if [ "$bonjour" = true ]; then
      echo "Bonjour, $1"
    else
      echo "$1"
    fi

    Testez avec bash demo.sh -b Alice puis bash demo.sh Alice. Vous obtenez un premier comportement optionnel, mais encore limité à une structure très simple.

  7. Remplacer l’analyse manuelle par getopts

    Éditeur de script Bash et terminal côte à côte pour illustrer le passage à une analyse d’options avec getopts.

    Créez un nouveau script plus propre pour gérer des options courtes :

    #!/usr/bin/env bash
    
    usage() {
      echo "Usage: $0 [-b] [-n NOM] cible"
    }
    
    bonjour=false
    nom=""
    
    while getopts ":bn:" opt; do
      case "$opt" in
        b)
          bonjour=true
          ;;
        n)
          nom="$OPTARG"
          ;;
        :)
          echo "Option -$OPTARG sans valeur"
          usage
          exit 1
          ;;
        \?)
          echo "Option invalide : -$OPTARG"
          usage
          exit 1
          ;;
      esac
    done

    Dans cette première version, -b active un mode, et -n attend une valeur. Le deux-points après n dans la chaîne d’options indique qu’un argument est requis pour cette option.

  8. Décaler les options lues pour récupérer l’argument restant

    Ajoutez la suite du script précédent :

    shift $((OPTIND - 1))
    
    if [ "$#" -eq 0 ]; then
      echo "Argument cible manquant"
      usage
      exit 1
    fi
    
    cible="$1"
    
    if [ "$bonjour" = true ]; then
      echo "Bonjour, $cible"
    else
      echo "Cible : $cible"
    fi
    
    if [ -n "$nom" ]; then
      echo "Nom fourni avec -n : $nom"
    fi

    Testez avec bash demo.sh -b -n Alice serveur. Après la boucle getopts, la variable OPTIND indique où commencent les arguments non encore traités, et shift vous place directement dessus.

  9. Gérer une option d’aide explicite

    Ajoutez une option -h pour afficher l’aide proprement :

    #!/usr/bin/env bash
    
    usage() {
      echo "Usage: $0 [-b] [-n NOM] [-h] cible"
    }
    
    bonjour=false
    nom=""
    
    while getopts ":bhn:" opt; do
      case "$opt" in
        b)
          bonjour=true
          ;;
        h)
          usage
          exit 0
          ;;
        n)
          nom="$OPTARG"
          ;;
        :)
          echo "Option -$OPTARG sans valeur"
          usage
          exit 1
          ;;
        \?)
          echo "Option invalide : -$OPTARG"
          usage
          exit 1
          ;;
      esac
    done
    
    shift $((OPTIND - 1))
    
    if [ "$#" -eq 0 ]; then
      echo "Argument cible manquant"
      usage
      exit 1
    fi
    
    echo "Cible : $1"

    Essayez bash demo.sh -h. Une aide explicite améliore l’usage quotidien du script et réduit les erreurs d’appel.

  10. Valider les arguments restants sans ambiguïté

    Faites maintenant respecter le nombre d’arguments attendus après les options :

    shift $((OPTIND - 1))
    
    if [ "$#" -ne 1 ]; then
      echo "Il faut exactement une cible"
      usage
      exit 1
    fi
    
    cible="$1"
    echo "Traitement de [$cible]"

    Testez plusieurs cas, comme zéro argument restant, un seul, puis deux. Cette validation rend le contrat du script clair et évite que des paramètres superflus soient ignorés sans signalement.

  11. Retransmettre correctement des arguments à une autre commande

    Créez un script dédié à la retransmission d’arguments :

    #!/usr/bin/env bash
    
    printf 'Arguments reçus :\n'
    for arg in "$@"; do
      printf '- [%s]\n' "$arg"
    done
    
    printf '\nRetransmission fidèle avec "$@" :\n'
    for arg in "$@"; do
      printf '> [%s]\n' "$arg"
    done

    L’idée à retenir est simple : quand vous devez réutiliser les arguments tels qu’ils ont été fournis, employez "$@". C’est le moyen standard pour préserver correctement les séparations entre arguments.

  12. Assembler un script complet avec options et cible

    Script Bash finalisé avec options et argument cible, visible dans un éditeur et exécuté dans un terminal.

    Terminez avec un script cohérent qui combine les éléments vus précédemment :

    #!/usr/bin/env bash
    
    usage() {
      echo "Usage: $0 [-b] [-n NOM] [-h] cible"
    }
    
    bonjour=false
    nom=""
    
    while getopts ":bhn:" opt; do
      case "$opt" in
        b)
          bonjour=true
          ;;
        h)
          usage
          exit 0
          ;;
        n)
          nom="$OPTARG"
          ;;
        :)
          echo "Option -$OPTARG sans valeur"
          usage
          exit 1
          ;;
        \?)
          echo "Option invalide : -$OPTARG"
          usage
          exit 1
          ;;
      esac
    done
    
    shift $((OPTIND - 1))
    
    if [ "$#" -ne 1 ]; then
      echo "Il faut exactement une cible"
      usage
      exit 1
    fi
    
    cible="$1"
    
    if [ "$bonjour" = true ]; then
      echo "Bonjour, $cible"
    else
      echo "Cible : $cible"
    fi
    
    if [ -n "$nom" ]; then
      echo "Nom optionnel : $nom"
    fi

    Testez des appels variés comme bash demo.sh serveur, bash demo.sh -b serveur et bash demo.sh -n Alice serveur. Vous disposez maintenant d’une base propre pour des scripts Bash débutants avec options et arguments séparés clairement.

Erreurs fréquentes & dépannage

L’erreur la plus fréquente consiste à confondre "$@" et "$*". Dans un script qui manipule plusieurs arguments, cette différence devient visible dès qu’un argument contient des espaces.

Une autre erreur classique est d’oublier le shift $((OPTIND - 1)) après getopts. Dans ce cas, les arguments restants ne sont pas lus au bon endroit.

Il est aussi courant de ne pas citer les variables comme "$1" ou "$OPTARG". Même dans des scripts simples, cette habitude peut créer des résultats inattendus dès qu’une valeur contient des espaces.

Astuces & pour aller plus loin

Testez toujours vos scripts avec plusieurs formes d’appel : sans argument, avec une option invalide, avec une option qui attend une valeur, et avec un argument contenant des espaces. Ces essais révèlent très tôt les ambiguïtés de conception.

Ajoutez systématiquement une fonction usage courte et lisible. Même un petit script devient plus agréable à utiliser quand son contrat d’entrée est affiché clairement.

Si votre script doit seulement gérer des options courtes simples, getopts offre une base pratique et intégrée à Bash. Pour rester lisible, gardez aussi une validation explicite du nombre d’arguments restants.

Questions fréquentes

À quoi sert $0 dans un script Bash ?

$0 contient le nom utilisé pour lancer le script. Il sert souvent à afficher un message d’aide comme Usage: $0 ....

Quand faut-il utiliser "$@" ?

Utilisez "$@" quand vous voulez parcourir ou retransmettre tous les arguments sans perdre leur séparation. C’est particulièrement important si certains arguments contiennent des espaces.

Quelle différence pratique entre "$@" et "$*" ?

Dans les exemples du tutoriel, "$@" conserve chaque argument comme élément distinct, tandis que "$*" les regroupe dans une seule chaîne dans une boucle de ce type. Pour la plupart des scripts débutants, "$@" est le choix le plus sûr.

Pourquoi utiliser getopts au lieu de tester $1 à la main ?

Tester $1 manuellement peut suffire pour une seule option très simple. Dès qu’il y a plusieurs options ou des options avec valeur, getopts rend le script plus clair et plus régulier.

À quoi sert OPTARG avec getopts ?

Quand une option attend une valeur, getopts place cette valeur dans OPTARG. Dans le tutoriel, l’option -n récupère ainsi le nom fourni par l’utilisateur.

Pourquoi faut-il faire shift après getopts ?

Après la lecture des options, shift $((OPTIND - 1)) repositionne les paramètres sur les arguments restants. Cela permet d’accéder proprement à la cible ou aux autres arguments non optionnels.

Conclusion

Vous savez maintenant lire $0, $1 et $#, parcourir correctement les arguments avec "$@", et distinguer ce comportement de "$*". Vous avez aussi mis en place une analyse propre des options courtes avec getopts.

Avec ces bases, vos scripts Bash deviennent plus prévisibles et plus agréables à utiliser. En conservant une aide claire, des variables citées et une validation stricte des arguments restants, vous éviterez la plupart des ambiguïtés courantes.

Commentaires · Aucun commentaire pour l'instant

Soyez le premier à réagir.

Laisser un commentaire