N. Exercices

Les exercices qui suivent testent et étendent votre connaissance de l'écriture de scripts. Pensez-les comme autant de défis, et comme des moyens distrayants d'avancer sur le chemin pierreux de l'expertise UNIX.


  Dans une ruelle minable de Hoboken (New Jersey) se trouve un
  squat insignifiant, un bâtiment en brique de deux étages,
  portant en façade une inscription gravée sur une plaque de
  marbre : 

Bash Scripting Hall of Fame.

À l'intérieur, parmi divers objets poussiéreux sans aucun intérêt, se trouve
exposée une plaque en laiton dans un état de corrosion avancée et
bordée de toiles d'araignées, portant la courte - très
courte - liste des quelques rares
personnes ayant pu maîtriser le contenu du Guide avancé 
de la programmation Bash
, ainsi qu'en témoigne
leur réussite aux exercices des sections suivantes.

      (Hélas, l'auteur du Guide ABS n'est pas
      représenté dans cette exposition. Peut-être à cause de certaines
      rumeurs malveillantes concernant son absence de qualification et ses 
      capacités limitées en programmation de scripts.)
      

N.1. Analyse de scripts

Examinez le script suivant. Lancez-le, puis expliquez ce qu'il fait. Annotez le script, puis ré-écrivez-le d'une façon plus compacte et plus élégante.

#!/bin/bash

MAX=10000


  for((nr=1; nr<$MAX; nr++))
  do

    let "t1 = nr % 5"
    if [ "$t1" -ne 3 ]
    then
      continue
    fi

    let "t2 = nr % 7"
    if [ "$t2" -ne 4 ]
    then
      continue
    fi

    let "t3 = nr % 9"
    if [ "$t3" -ne 5 ]
    then
      continue
    fi

  break   # Que se passe-t-il quand vous mettez cette ligne en commentaire ?
          # Pourquoi ?

  done

  echo "Nombre = $nr"


exit 0

---

Expliquez ce que fait le script suivant. C'est réellement seulement un tube paramétré en ligne de commande.

#!/bin/bash

REPERTOIRE=/usr/bin
TYPEFICHIER="shell script"
JOURNAL=logfile

file "$REPERTOIRE"/* | fgrep "$TYPEFICHIER" | tee $JOURNAL | wc -l

exit 0

---

Examinez et expliquez le script suivant. Pour vous aider : find et stat.

#!/bin/bash

# Auteur :  Nathan Coulter
# Ce code est dans le domaine public.
# L'auteur a donné sa permission d'utiliser ce code dans le guide ABS.

find -maxdepth 1 -type f -printf '%f\000'  | {
   while read -d $'\000'; do
      mv "$REPLY" "$(date -d "$(stat -c '%y' "$REPLY") " '+%Y%m%d%H%M%S'
      )-$REPLY"
   done
}

# Attention : testez ce script dans un répertoire de tests.
# Car il touche aux fichiers qui en font partie.

---

Un lecteur a envoyé le code suivant.

while read LIGNE
do
  echo $LIGNE
done < `tail -f /var/log/messages`

Il souhaitait écrire un script traçant les modifications dans le journal système, /var/log/messages. Malheureusement, le bloc de code ci-dessus se bloque et ne fait rien d'utile. Pourquoi ? Corrigez-le pour qu'il fonctionne (indice : plutôt que de rediriger l'entrée standard stdin de la boucle, essayez un tube).

---

Analyser le « code sur une ligne » (ici séparé sur deux lignes pour plus de clareté) contribué par Rory Winston :

export SUM=0; for f in $(find src -name "*.java");
do export SUM=$(($SUM + $(wc -l $f | awk '{ print $1 }'))); done; echo $SUM

Astuce : tout d'abord, diviser le script en petites sections. Puis, examinez avec attention son utilisation de l'arithmétique par parenthèses doubles, et des commandes export, find, wc et awk.

---

Analyser l'Exemple A.10, « Le Jeu de la Vie » et ré-organisez-le en suivant un style simplifié et plus logique. Cherchez combien de ses variables peuvent être éliminées et essayez d'optimiser le temps d'exécution du script.

Modifiez le script pour qu'il accepte n'importe quel fichier texte ASCII pour sa « génération » initiale. Le script lira les $ROW*$COL premiers caractères et initialisera les occurences de voyelles comme des cellules « vivantes ». Indice : assurez-vous de remplacer les espaces dans le fichier d'entrée par des caractères 'tiret bas'.