Bash exemples

Linux: le Shell par l'Exemple, par quelqu'un qui n'y entend rien, ou si peu

alain Adelmar
aadelmar@numericable.fr beuuh c est quoi ca

Comme l'esprit libre le sugére et le bon sens aussi, un OS qui permet à ce que l'utilisateur puisse ouvrir,  éditer, questionner, décortiquer, modifier jusque aux structures même de ses fichiers, doit être furieusement pratiqué par les exipérences de chacun afin de pouvoir satisfaire la curiosité maladive de ses utilisateurs (users en anglais). Même si l'utilité de ces dit tests ne vous semble pas indispensable à priori. C'est en forgant qu'on devient forgeron et c'est en shellant qu'on devient Linuxiste amateur(et non pas ringo ou bashelier).
Voilà, je suis un débutant de fraîche date et je galère pas mal pour trouver des documents traitant de script et qui soit commentés pour ce faire une idée .



Ce petit shell ne sert que pour l'exemple, mais peut être inséré dans un autre plus grand, il vérifi si le login de l'utilisateur est connu comme compte utilisateur.
Les commentères sont présédé du signe # est sont facultatifs.
La première ligne, est la ligne qui désigne quel langage doit traiter ce script (sh , csh, bash, ash ou perl  )

#!/bin/sh

if [ ! $1 ]
then
 echo "Bonjour qui est la ?"
 echo "Quel est ton nom utilisateur ?"
 exit 1
fi
NOM=$1
if grep $NOM /etc/passwd > /dev/null
then
  echo "Oui, je te connais $NOM"
  exit 0
else
  echo "Non ça ne me dit rien"
fi
exit 0

----------------------------------------------*------------
#!/bin/sh
# dans le rep choisi ($DIR)
DIR=$1
# pour tout les pattern $a contenu dans $DIR
for a in `ls $DIR`
do
# fname de $a traduit en Maj les min
fname=`echo $a | tr a-z A-Z`
# bouge rep des instances de $a en rep de sortie de $fname
mv $DIR/$a $DIR/$fname
done;
exit 0
# remd: ce script tranforme tous les noms de fichier minuscule en MAJ
# il suffi d'entrer le chemin du rep ou le changement dois s'effectuer.
# alain adelmar d'apres exemple, le 2 Mai 2000.

---------------------------------------------*-----------------

Dans ce script "WhoMe.sh" il faudra entrer son nom aprés la commande comme ceci:
$ WhoMe.sh "alain" sinon rien ne ce passe (visuellement en tout cas. Le script ne s'arréte pas non plus si on ne met pas son nom entre guillemets, ce qui peut vouloir dire que le script n'a pas retourné quoi que ce soit, peut être est-ce la variable qui n'est pas considérée comme tel.
De la rigueur donc, car une variable peut etre confondue avec une suite d'options.

Ce qu'on peut déduire dans ce script:

#!/bin/sh

# initialisation de la variable ME avec le premier paramêtre suivant la commande
# ne pas oublier de la placer entre guillemets "".
ME=$1

# recherche du modèle $ME dans le fichier passwd (sans affichage).
if grep $ME /etc/passwd > /dev/null
# si oui alors
then

 # affiche le message " ".
 echo "Oui, vous êtes un utilisateur de cette machine."

# sinon
else
 # affiche le message " ".
 echo "No Way, Circulez !"
fi
exit 0

Voilà fastoche non ? Et que de possibilitées ouvertes sachant qu'il existe d'autres commandes et contrôles .

--------------------------------------------*--------------

#!/bin/sh
if [ ! $1 ]
    then
    echo "depuis quel fichier ?"
    exit 1
fi
if [ ! $2 ]
    then
 echo "dans quel fichier ?"
 exit 1
fi

FNM=$1
FNF=$2

sort -d $FNM
uniq $FNM >> $FNF
exit 0

------------------------------------------------*-------------

#include <stdio.h>
main () {
 int centigrade, farenheit;

 printf("\n\tConvertion: n°C -> n°F\n");
 /* un peu de pub ça ne tue pas */
 printf ("\toffert by: a_l_a_i_n/*/a_d_e_l_m_a_r\n\n");
 /* la boucle for */
 for(centigrade = -20; centigrade <=50; centigrade += 5) {
  farenheit = 32 + centigrade * 1.8;
  printf("\t%d°C -> %d°F\n", centigrade, farenheit);
  }
  return 0;
}

-------------------------------------------------*---------
#!/bin/sh
# remd: ce shell transforme les fichiers texte du dos =>linux

FTD=$1
FTL=$2

$FND="./UnixTextDefault"
$RESP=[o, O, Yes, yes]

if [ ! $1 ]
then
    echo "Usage: nommez le fichier texte dos à convertir"
    exit 1
fi

if [ ! $2 ]
then
    echo "existe t'il un fichier cible?"
    read $RESP
    if $RESP=false
    then
 touch $3
 exit 1
    fi
fi

tr -d `\015` < $1 > $2
exit 0
-----------------------------------------------*----------------

Brouillon script Bash d'après l'article dans la lx_gazette/lfo
voir sur http://www.linux-france/documents/lx_gazette/Issue-2/

exemple de script shell

#!/bin/sh
# notation indiquant que les commande seront executé par le shell (.sh)

DIR=$1
# initialise la variable DIR avec le premier paramètre (entrée aprés la commande)

for a in `ls $DIR`
# pour toute entre "a" obtenu par la commande "ls $DIR"
do
fname=`echo $a | tr A-Z a-z`
# la fonction fname
mv $DIR|$a $DIR|$fname
done
exit 0
# ce script affichera une erreur si le nom du fichier est deja en minuscule
# et suppose que son param.tre est un repertoire.
# voir: man bash(1).

plus loin

autre exemple en reprenant le script premier script qui n'accéptait que des noms entiers

if [ ! $1 ]
# qui signifie:   si $1 faux
ou plutot         si $1 inexistant
car si il existe il sera vrai vu que l'on a demander juste si l'argument $1 (qui est en fait le premier argument, option, mot placer aprés le nom_du_script désigner par $1).
exemple:     si je tape
mon_script est super chouette
mon_script     est considéré comme le nom du script et est placé dans une variable sous le label $0
est                 est considéré comme premier argument et est placé dans une variable sous l'appelation $1
super             est considéré comme second argument et est placé dans une variable sous l'appelation $2
chouet           est considéré comme troisiéme argument et est placé dans une variable sous l'appelation $3

La nouveauté est l'utilisation du point d'exclamation en tant qu'opérateur logique NOT.
Utilisons cela dans notre programme et regardons sa construction.

#!/bin/sh

if [ ! $1 ]
then
   echo "Mode d'emploi: `basename $0` nom_repertoire à modifier"
 exit 1
fi
DIR=$1
for a in `ls $DIR`
do
fname=`echo $a | tr A-Z a-z`
mv $DIR/$a $DIR/$fname
done;

Désormais, si l'utilisateur tape la commande sans le répertoire, le script se terminera en produisant un message sur la façon adéquate de l'invoquer, suivi d'un code erreur de 1.

Que se passe-t-il si l'on ne veut changer que le nom d'un seul fichier ? On a déjà cette commande et ce serait bien si elle pouvait s'en charger. Si l'on veut faire cela, il faut pouvoir tester si le paramètre est un fichier de quel type est ce fichier ou ce répertoire.
Important: Voici une liste des opérateurs de test portant sur les fichiers :

-b fichier
 Vrai si fichier est un fichier spécial de type bloc

-c fichier
  Vrai si fichier est un fichier spécial de type caractère

-d fichier
 Vrai si fichier est un répertoire

-f fichier
 Vrai si fichier est un fichier ordinaire

-r fichier
 Vrai si fichier est un fichier accessible en lecture

-w fichier
 Vrai si fichier est un fichier accessible en écriture

-x fichier
 Vrai si fichier est un fichier exécutable

Il y a d'autres opérateurs mais ceux-ci sont les plus utilisés. Maintenant, on peut tester si notre script a en entrée un répertoire ou un fichier : modifions donc encore un peu le programme.

1    #!/bin/sh
2
3    if [ ! $1 ]
4    then
5     echo "Usage: `basename $0` nom_repertoire"
6     exit 1
7    fi
8
9    if [ -d $1 ]
10    then
11     DIR="/$1"
12    fi
13
14    if [ -f $1 ]
15    then
16     DIR=""
17    fi
18
19    for a in `ls $DIR`
20    do
21     fname=`echo $a | tr A-Z a-z`
22     mv $DIR$a $DIR$fname
23    done;

Nous avons inséré les lignes 9 à 17 pour effectuer les vérifications fichier/répertoire. S'il s'agit d'un répertoire, on initialise DIR à « /$1 », sinon on l'initialise à vide. Remarquez que l'on met maintenant le / du répertoire dans la variable DIR et que nous avons modifié la ligne 22 pour qu'il n'y ait pas de / entre $DIR et $a. Avec cette méthode, les chemins sont corrects.
On a encore quelques problèmes. L'un d'eux est que, si un fichier porte déjà le nom que nous voulons attribuer, le script produit une erreur. On doit donc vérifier le nouveau nom de fichier avant de renommer. Un autre problème est de savoir ce qui se passe si quelqu'un met plus d'un paramètre. Nous allons modifier notre script pour accepter plus d'un répertoire ou fichier.
Le premier problème se corrige facilement en utilisant un simple test de chaîne et une instruction if, comme nous l'avons fait plus haut. Le deuxième problème est légèrement plus difficile car nous devons connaître le nombre de paramètres que l'utilisateur a fourni en entrée. Pour obtenir cette information, on utilise une variable spéciale du shell, toute préparée pour nous. Il s'agit de la variable $# qui contient le nombre de paramètres de la ligne de commande. Ce que nous voulons faire est une boucle sur tous les paramètres. Cette fois-ci, nous utiliserons la boucle while pour faire ce travail. Enfin, nous aurons besoin de comparer des valeurs entières car on veut pouvoir comparer le nombre de fois où l'on est passé dans la boucle au nombre de paramètres. Il existe des options de test spéciales pour évaluer les entiers, les voici :

 int1 -eq int2
      (equal) Vrai si l'entier 1 est égal à l'entier 2.

 int1 -ge int2
      (greater or equal) Vrai si l'entier 1 est supérieur ou égal à l'entier 2.

 int1 -gt int2
      ((greater than) Vrai si l'entier 1 est supérieur à l'entier 2.

 int1 -le int2
      (lesser or equal) Vrai si l'entier 1 est inférieur ou égal à l'entier 2.

 int1 -lt int2
      (lesser than) Vrai si l'entier 1 est inférieur à l'entier 2.

 int1 -ne int2
      (nor equal) Vrai si l'entier 1 est différent de l'entier 2.

Avec ces nouvelles informations, nous pouvons modifier notre programme.

    #!/bin/sh
    if [ ! $1 ]
    then
      echo "Usage: `basename $0` nom_repertoire"
      exit 1
    fi

    while [ $# -ne 0  ]
    do
    if [ -d $1 ]
    then
       DIR="/$1"
    fi
    if [ -f $1 ]
    then
      DIR=""
    fi

    for a in `ls $DIR`
    do
      fname=`echo $a | tr A-Z a-z`
      if [ $fname != $a ]
      then
        mv $DIR$a $DIR$fname
      fi
    done;
    shift
  done

   Nous avons inséré une boucle while en ligne 9 qui vérifie si le nombre de paramètres est égal à zéro. Cela peut ressembler à une boucle sans fin mais l'instruction shift en ligne 30 nous sauve. Elle annule le paramètre le plus proche du nom de la commande et le remplace par le suivant. Cette boucle annulera tous les paramètres éventuels : leur nombre sera alors de zéro, ce qui terminera la boucle.

Enfin, remarquez l'instruction if en ligne 24 : elle vérifie si le nom de fichier est déjà en minuscules et, si c'est le cas, l'ignore.

J'espère que vous avez apprécié cette brève introduction à la programmation Bourne/Bash. Je vous encourage à essayer vous-même ces exemples. En fait, si vous pourriez améliorer ce script en lui ajoutant une option comme -m pour les minuscules et -M pour les majuscules.

Je rappelle que ce script n'est pas de moi, je vous conseille d'aller voir l'original sur lfo à la rubrique linux-gazette ainsi que les autres articles super chouets (pour tout niveaux).

retour