A la découverte d'UNIX (FreeBSD)
Last updated on Tuesday, January 8, 2013
  • 4 semaines
  • Moyen

Free online content available in this course.

Got it!

Autres exemples de scripts

Dans ce chapitre, vous allez vous exercer à utiliser les notions vues précédemment. Et découvrir, à travers des exemples, quelques commandes supplémentaires...

A - Un "date" plus convivial

La commande date affiche la date et l'heure courantes sous cette forme :

% date
Fri Jun 17 15:11:30 CEST 2011

Simple et efficace. Mais pas forcément très convivial, :( surtout pour les francophones que nous sommes.

Nous allons créer une commande basée sur date, que nous appellerons heure, et qui affichera la même information sous la forme :

% heure
Bonjour. Nous sommes le vendredi 17 juin 2011.
Il est 15 heures et 11 minutes.

Plus sympa, non ? :)

Commencez bien sûr par créer un fichier heure. Nous allons mettre dans un tableau complet l'ensemble des informations fournies par la commande date.

#!/bin/csh

set complet = (`date`)

Dans l'exemple ci-dessus, complet est maintenant un tableau de 6 cases :

  • Fri

  • Jun

  • 17

  • 15:11:30

  • CEST

  • 2011

La première case, Fri, indique que nous sommes vendredi. Encore faut-il l'expliquer à votre script. C'est ce que nous allons faire maintenant, avec un switch :

#jour
switch ($complet[1])
   case Mon
      set jour = lundi
   breaksw
   case Tue
      set jour = mardi
   breaksw
   case Wed
      set jour = mercredi
   breaksw
   case Thu
      set jour = jeudi
   breaksw
   case Fri
      set jour = vendredi
   breaksw
   case Sat
      set jour = samedi
   breaksw
   case Sun
      set jour = dimanche
   breaksw
endsw

Pour le mois (case n°2), on peut naturellement employer la même méthode. Je vous propose cette variante, plus courte à écrire, qui fait intervenir 2 tableaux supplémentaires :

  • court : pour les noms courts des mois en Anglais.

  • long : pour les nom longs des mois en Français.

#mois
set court = (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
set long = (janvier fevrier mars avril mai juin juillet aout\
septembre octobre novembre decembre)

Vous reconnaissez le symbole \, pour continuer l'instruction sur la ligne suivante.

Maintenant, nous allons parcourir ces deux tableaux avec un foreach, jusqu'à rencontrer le nom court correspondant à celui que date nous indique. On lit alors dans le tableau long le nom complet et français de ce mois.

foreach i (1 2 3 4 5 6 7 8 9 10 11 12)
   if ($complet[2] == $court[$i]) set mois = $long[$i]
end

La troisième case du tableau complet contient le numéro du jour dans le mois (17).

#numero du jour
set numero = $complet[3]

Pour les heures et les minutes, on a un problème : ces deux informations se trouvent dans la même case : 15:11:30. Il va falloir faire un peu des découpage. À vos ciseaux, ça va trancher ! :pirate:

Je vous rappelle que la sortie de la commande date est :

% date
Fri Jun 17 15:11:30 CEST 2011

On envoie d'abord cette sortie dans un fichier texte (date.txt), puis on l'y découpe avec la commande cut en suivant les pointillés (les :).

#heures et minutes
date > date.txt
set debut = (`cut -d : -f 1 date.txt`)
set milieu = (`cut -d : -f 2 date.txt`)
set fin = (`cut -d : -f 3 date.txt`)

Il faut d'abord que je vous explique la commande cut proprement dite.

% cut -d : -f 1 date.txt

Cette ligne découpe le fichier date.txt en prenant comme limite le caractère :. Comme ce caractère apparaît deux fois dans Fri Jun 17 15:11:30 CEST 2011, cela nous donne trois tranches :

  • Fri Jun 17 15

  • 11

  • 30 CEST 2011

L'option -f 1 indique qu'il faut conserver la première de ces trois tranches.

Dans notre script, on a donc créé trois tableaux : debut, milieu et fin. Chacun contient l'une des trois tranches de date.txt.

  • debut est un tableau de 4 cases : Fri Jun 17 15.

  • milieu est un tableau d'une seule case (11) donc une variable ordinaire.

  • fin est un tableau de 3 cases : 30 CEST 2011.

La case n°4 du tableau debut correspond aux heures et la variable milieu aux minutes.

set heures = $debut[4]
set minutes = $milieu

Dans le tableau fin, nous pouvons récupérer l'année courante (case n°3).

#annee
set annee = $fin[3]

Nous avons maintenant toutes les informations nécessaires pour répondre à l'utilisateur :

#affichage
echo "Bonjour. Nous sommes le $jour $numero $mois $annee."
echo "Il est $heures heures et $minutes minutes."

Le script complet est donc :

#!/bin/csh

set complet = (`date`)

#jour
switch ($complet[1])
   case Mon
      set jour = lundi
   breaksw
   case Tue
      set jour = mardi
   breaksw
   case Wed
      set jour = mercredi
   breaksw
   case Thu
      set jour = jeudi
   breaksw
   case Fri
      set jour = vendredi
   breaksw
   case Sat
      set jour = samedi
   breaksw
   case Sun
      set jour = dimanche
   breaksw
endsw

#mois
set court = (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
set long = (janvier fevrier mars avril mai juin juillet aout\
septembre octobre novembre decembre)

foreach i (1 2 3 4 5 6 7 8 9 10 11 12)
   if ($complet[2] == $court[$i]) set mois = $long[$i]
end

#numero du jour
set numero = $complet[3]

#heures et minutes
date > date.txt
set debut = (`cut -d : -f 1 date.txt`)
set milieu = (`cut -d : -f 2 date.txt`)
set fin = (`cut -d : -f 3 date.txt`)

set heures = $debut[4]
set minutes = $milieu

#annee
set annee = $fin[3]

#affichage
echo "Bonjour. Nous sommes le $jour $numero $mois $annee."
echo "Il est $heures heures et $minutes minutes."

Copiez ce script dans le dossier /usr/local/bin/ pour pouvoir appeler la commande heure n'importe quand. Et n'oubliez pas d'exécuter la commande :

% chmod 711 heure

Ainsi, vous avez tous les droits sur ce fichier et les autres utilisateurs ont le droit de l'exécuter.

B - Analyse d'un fichier

Ce script va s'appeler rapport. Son rôle est d'analyser un fichier et de nous présenter un bref compte-rendu. Par exemple, si on veut analyser le script change du chapitre précédent, on verra :

% rapport change
Le fichier change appartient a l'utilisateur brice et au groupe brice.
Sa derniere modification date du 17 juin a 11:47.
Il pese 1859 Ko et comporte 236 mots repartis en 61 lignes.

Les informations affichées ici sont fournies par deux commandes. La première, vous la connaissez déjà, c'est ls -l :

% ls -l change
-rwxr-x--x  1 brice  brice  1859 Jun 17 11:47 change

L'autre s'appelle wc (word count). Elle indique le nombre de mots et le nombre de lignes dans le fichier puis sa taille :

% wc change
      61     236    1859 change

Vous savez maintenant comment enregistrer dans des tableaux les informations fournies par ces deux commandes :

#!/bin/csh

set tabls = (`ls -l $argv`)
set tabwc = (`wc $argv`)

Le fichier s'appelle change. Qu'est-ce que c'est que ce $argv ? Nous n'avons défini aucune variable de ce nom. :o

Je ne sais pas si vous l'avez remarqué, mais il y a une grosse différence entre ce script et tous ceux que je vous ai montrés jusqu'à maintenant. Pour l'exécuter, vous n'ecrivez pas seulement son nom. Vous indiquez aussi le nom du fichier que vous voulez analyser :

% rapport heure

On dit que vous donnez un argument au script au moment où vous l'appelez. Ici, c'est le nom du fichier à analyser qui sert d'argument. De la même manière, quand vous tapez cd /usr/local pour vous rendre dans ce dossier, vous fournissez à la commande cd l'argument /usr/local, qui correspond à votre destination.

L'argument fourni au script est automatiquement enregistré dans une variable, qu'on n'a pas besoin de définir manuellement, et qui s'appelle toujours argv.

Si vous lancez le script rapport en lui donnant l'argument heure, alors la variable argv prend la valeur heure. La fois suivante, pour pourrez lancer le même script en lui donnant l'argument change. On aura alors $argv = change.

Revenons à nos moutons. Nous avons donc demandé :

% rapport change

Rien ne s'affiche, naturellement. Mais deux tableaux ont été créés : tabls (9 cases) et tabwc (4 cases) :

-rwxr-x--x  1  brice  brice  1859  Jun  17  11:47  change

61  236  1859  change

L'étape suivante est assez simple, et n'est d'ailleurs pas forcément indispensable. On lit dans les deux tableaux chacune des informations dont nous avons besoin :

set user = $tabls[3]
set groupe = $tabls[4]
set jour = $tabls[7]
set heure = $tabls[8]
set taille = $tabls[5]

set lignes = $tabwc[1]
set mots = $tabwc[2]

Pour le mois, ls -l nous donne Jun. On ne peut pas le laisser sous cette forme-la. Il faut le traduire en juin. Comme nous l'avons déjà fait dans le script heure, il suffit de reprendre le même code :

#mois
set court = (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
set long = (janvier fevrier mars avril mai juin juillet aout\
septembre octobre novembre decembre)

foreach i (1 2 3 4 5 6 7 8 9 10 11 12)
   if ($tabls[6] == $court[$i]) set mois = $long[$i]
end

OK, ce n'est pas exactement le même code. Dans le if, nous avons remplacé $complet[2], c'est à dire le nom du mois à traduire, par $tabls[6].

Mais c'est la seule différence. Ce bloc de quelques lignes, chargé de traduire l'abréviation d'un mois anglais en nom complet d'un mois français nous a servi dans deux scripts différents. Et il est susceptible de resservir dans d'autres scripts encore. Il peut donc être intéressant d'en faire un script à part entière, que nous appellerons tradMois :

#!/bin/csh
                            
set court = (Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
set long = (janvier fevrier mars avril mai juin juillet aout\
septembre octobre novembre decembre)

foreach i (1 2 3 4 5 6 7 8 9 10 11 12)
   if ($argv == $court[$i]) echo $long[$i]
end

Après avoir activé ce script avec chmod, on lui donne l'abréviation à traduire comme argument. Il affiche la traduction :

% tradMois Aug
aout

On peut maintenant appeler le script tradMois à l'intérieur du script rapport :

set mois = `tradMois $tabls[6]`

Vous reconnaissez les apostrophes "spéciales" de la touche 7, pour demander l'exécution de tradMois.

Il ne reste plus qu'à afficher le rapport. Pour changer un peu, je n'utilise pas la commande echo mais l'une de ses cousines : printf.

#!/bin/csh

set tabls = (`ls -l $argv`)
set tabwc = (`wc $argv`)

set user = $tabls[3]
set groupe = $tabls[4]
set jour = $tabls[7]
set heure = $tabls[8]
set taille = $tabls[5]

set lignes = $tabwc[1]
set mots = $tabwc[2]

set mois = `tradMois $tabls[6]`

printf "Le fichier $argv appartient a l'utilisateur $user et au groupe $groupe.\
Sa derniere modification date du $jour $mois a $heure.\
Il pese $taille Ko et comporte $mots mots repartis en $lignes lignes.\n"

Dans le printf, les \ en fin de ligne signifient que l'instruction continue à la ligne suivante. Le final, quant à lui, indique qu'il faut aller à la ligne avant de rendre la main à l'utilisateur.

Un petit coup de chmod et on essaie :

% rapport rapport
Le fichier rapport appartient a l'utilisateur brice et au groupe brice.
Sa derniere modification date du 18 juin a 21:25.
Il pese 467 Ko et comporte 78 mots repartis en 21 lignes.

Pour finir, sachez qu'un script peut parfaitement recevoir plusieurs arguments. Dans ce cas, argv n'est plus une simple variable mais un tableau. Imaginons, par exemple, que vous vouliez analyser plusieurs fichiers. Le script rapports, ci-dessous, vous donnera entière satisfaction. Avec une boucle while, il appelle à plusieurs reprises le programme rapport (au singulier) ci-dessus :

#!/bin/csh

echo "Vous avez demande l'analyse des fichiers suivants : $argv[*]"

set i=1
while ($i <= $#argv)
   printf "\n"        #On saute une ligne
   rapport $argv[$i]
   @ i++
end

$argv[*] représente l'ensemble des valeurs du tableau (donc l'ensemble des fichiers à analyser). Il existe deux notations quasiment équivalentes : $argv ou, tout simplement $*. Je dis quasiment car, pour certaines opérations particulières sur les tableaux (copier un tableau dans un autre, par exemple), la notation $argv[*] est indispensable.

Un peu plus bas, vous rencontrez $#argv. C'est le nombre d'arguments que le script à reçu. Dans notre cas, c'est donc le nombre de fichiers à analyser.

La variable i va prendre successivement les valeurs 1, 2, 3, ... jusqu'à $#argv. $argv[i] sera donc d'abord $argv[1] puis $argv[2], etc. Il adoptera tour à tour le contenu de chacune des cases du tableau argv. On peut aussi les appeler $1, $2, etc.

Il faut que je vous explique l'avant-dernière ligne : @ i++. Le symbole @ signifie qu'on fait un calcul. Et i++, c'est une astuce bien connue pour augmenter de 1 la valeur de la variable i. C'est la même chose que i = i + 1. C'est tellement courant qu'il y a un mot spécial pour cette augmentation de 1 : une incrémentation. Ici, l'incrémentation permet de passer à la case suivante du tableau pour le prochain tour de la boucle while.

Voyons si ça fonctionne :

% rapports heure change rapport
Vous avez demande l'analyse des fichiers suivants : heure change rapport

Le fichier heure appartient a l'utilisateur brice et au groupe brice.
Sa derniere modification date du 18 juin a 11:35.
Il pese 1057 Ko et comporte 183 mots repartis en 56 lignes.

Le fichier change appartient a l'utilisateur brice et au groupe brice.
Sa derniere modification date du 17 juin a 11:47.
Il pese 1859 Ko et comporte 236 mots repartis en 61 lignes.

Le fichier rapport appartient a l'utilisateur brice et au groupe brice.
Sa derniere modification date du 18 juin a 21:25.
Il pese 467 Ko et comporte 78 mots repartis en 21 lignes.
Example of certificate of achievement
Example of certificate of achievement