32. Écrire des scripts avec style

Prenez l'habitude d'écrire vos scripts shell d'une façon structurée et méthodique. Même des scripts écrits « sur le dos d'une enveloppe » et « sans trop réfléchir » peuvent en bénéficier si vous prenez le temps de plannifier et d'organiser vos pensées avant de vous assoir pour l'écrire.

Du coup, il existe quelques lignes de conduites pour le style. Ceci n'a pas pour but d'être la feuille de style officielle pour l'écriture de scripts.

32.1. Feuille de style non officielle d'écriture de scripts

  • Commentez votre code. Cela le rend plus facile à comprendre (et apprécier) par les autres, et plus facile pour vous à maintenir.

    PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
    #  Cela avait un sens lorsque vous l'aviez écrit l'année dernière, mais
    #+ c'est un mystère complet.
    # (À partir du script "pw.sh" de Antek Sawicki.)
    

    Ajoutez des en-têtes descriptives à votre script et à vos fonctions.

    #!/bin/bash
    
    #************************************************#
    #                   xyz.sh                       #
    #          écrit par by Bozo Bozeman             #
    #                05 Juil. 2001                   #
    #                                                #
    #   Fait le ménage dans les fichiers projets.    #
    #************************************************#
    
    E_MAUVAISREPERTOIRE=65          # Répertoire inexistant.
    rep_projets=/home/bozo/projects # Répertoire à nettoyer.
    
    # ----------------------------------------------------------- #
    # nettoie_pfichiers ()                                        #
    # Supprime tous les fichiers dans le répertoire indiqué.      #
    # Paramètre : $repertoire_cible                               #
    # Renvoie   : 0 en cas de succès, $E_MAUVAISREPERTOIRE sinon. #
    # ----------------------------------------------------------- #
    nettoie_pfichiers ()
    {
      if [ ! -d "$1" ]  # Teste si le répertoire cible existe.
      then
        echo "$1 n'est pas un répertoire."
        return $E_MAUVAISREPERTOIRE
      fi
    
      rm -f "$1"/*
      return 0   # Succès.
    }
    
    nettoie_pfichiers $rep_projets
    
    exit 0
    

    Assurez-vous de mettre le #!/bin/bash au début de la première ligne d'un script, précédant tout en-tête de commentaires.

  • Éviter d'utiliser des « nombres magiques », [87] c'est-à-dire des constantes littérales « codées en dur ». Utilisez des noms de variables significatifs à la place. Ceci rend le script plus facile à comprendre et permet de faire des changements et des mises à jour sans casser l'application.

    if [ -f /var/log/messages ]
    then
      ...
    fi
    # Un an après, vous décidez de changer le script pour vérifier /var/log/syslog.
    #  Il est maintenant nécessaire de changer manuellement le script, instance par
    #+ instance, et espérer ne rien casser.
    
    # Un meilleur moyen :
    FICHIERTRACE=/var/log/messages  # Seule une ligne a besoin d'être modifié.
    if [ -f "$FICHIERTRACE" ]
    then
      ...
    fi
    
  • Choisissez des noms descriptifs pour les variables et les fonctions.

    fl=`ls -al $nomrep`                  # Crypté.
    liste_fichiers=`ls -al $nomrep`      # Mieux.
    
    
    VALMAX=10   # Tout en majuscule pour les constantes du script.
    while [ "$index" -le "$VALMAX" ]
    ...
    
    
    E_PASTROUVE=75                       # Tout en majuscule pour les codes d'erreur,
                                         # et leur nom commence par "E_".
    if [ ! -e "$nomfichier" ]
    then
      echo "Fichier $nomfichier introuvable."
      exit $E_PASTROUVE
    fi
    
    
    REPERTOIRE_MAIL=/var/spool/mail/bozo # Tout en majuscule pour une variable d'environnement.
    export REPERTOIRE_MAIL
    
    
    ObtientReponse ()                    # Majuscule et minuscule pour une fonction.
    {
      invite=$1
      echo -n $invite
      read reponse
      return $reponse
    }
    
    ObtientReponse "Quel est votre nombre favori ? "
    nombre_favori=$?
    echo $nombre_favori
    
    
    _variableutilisateur=23              # OK, mais pas recommandé.
    #  Il est mieux pour les variables définies par les utilisateurs de ne pas
    #+ commencer avec un tiret bas.
    # Laissez cela pour les variables système.
    
  • Utiliser des codes de sortie d'une façon systématique et significative.

    E_MAUVAIS_ARGS=65
    ...
    ...
    exit $E_MAUVAIS_ARGS
    

    Voir aussi l'Annexe D, Codes de sortie ayant une signification particulière.

    Ender suggère l'utilisation des codes de sortie contenus dans /usr/include/sysexits.h dans les scripts shell bien qu'ils aient pour but la programmation en C et C++.

  • Utilisez les options de paramètres standardisées pour l'appel de script. Ender propose l'ensemble d'options suivant.

    -a      All: renvoie toutes les informations
            (incluant les informations de fichiers cachés).
    -b      Bref: Version courte, généralement pour les autres scripts.
    -c      Copie, concatène, etc.
    -d      Daily: Utilise l'information du jour complet et non pas seulement
            l'information pour une instance ou pour un utilisateur spécifique.
    -e      Étendu/Élaboré: (n'inclut souvent pas les informations de fichiers
            cachés).
    -h      Help: Aide, indication verbeuse sur l'utilisation avec description,
            discussion, aide.
            Voir aussi -V.
    -l      Traces du script.
    -m      Manuel: page man de la commande de base.
    -n      Nombre: Données numériques seulement.
    -r      Récursif: Tous les fichiers d'un répertoire (et/ou tous les
            sous-répertoires).
    -s      Setup & Maintenance fichier: Fichier de configuration de ce script.
    -u      Usage: Liste des options à l'appel du script.
    -v      Verbeux: Sortie lisible par un humain, plus ou moins formaté.
    -V      Version / Licence / Copy(right|left) / Contributions (par courrier
            électronique aussi).
    

    Voir aussi l'Section F.1, « Options standards en ligne de commande ».

  • Casser les scripts complexes en modules plus simples. Utiliser des fonctions si c'est approprié. Voir l'Exemple 34.4, « Utiliser des tableaux et autres astuces pour gérer quatre mains aléatoires dans un jeu de cartes ».

  • N'utilisez pas une construction complexe lorsqu'une construction plus simple fait l'affaire.

    COMMANDE
    if [ $? -eq 0 ]
    ...
    # Redondant et non intuitif.
    
    if COMMANDE
    ...
    # Plus concis (même si moins compréhensible).
    

... reading the UNIX source code to the Bourne shell (/bin/sh). I was shocked at how much simple algorithms could be made cryptic, and therefore useless, by a poor choice of code style. I asked myself, « Could someone be proud of this code? »

... lisant le code source UNIX du shell Bourne (/bin/sh). J'ai été choqué de voir à quel point de simples algorithmes pouvaient être rendus incompréhensibles, et du coup inutiles, par un mauvais choix dans le style de codage. Je me suis demandé, « Quelqu'un peut-il être fier de ce code ? »

--Landon Noll


[87] Dans ce contexte, les « nombres magiques  » ont une signification entièrement différente que les nombres magiques utilisés pour désigner les types de fichier.