PROFDINFO.COM

Votre enseignant d'informatique en ligne

Labo 7 - Exercices supplémentaires (solutions)

Retour à la page du cours

Cette section contient plusieurs exercices supplémentaires pour vous pratiquer. Ces exercices ne sont pas obligatoires et ne seront pas notés. Vous pouvez les faire si vous voulez et me poser des questions si vous avez besoin d'aide pour y arriver. Les réponses seront placées sur le site plus tard pendant la semaine.

7.1 - Le compteur de fichiers

7.2 - Le créateur de HTML

7.3 - CreerUsager v3.0

7.1 - Le compteur de fichiers

Réalisez un script qui accepte un nom de répertoire en paramètre et qui va faire le compte des fichiers et des répertoires qu'il contient.

Par exemple, si on l'appelle ainsi:

compteur /etc

Il produit la sortie suivante:

Le repertoire /etc contient 95 fichiers et 128 sous-repertoires.

Si on l'appelle avec le mauvais nombre de paramètres, il doit nous afficher un message d'aide expliquant comment l'utiliser et terminer avec le code de retour 1.

Si on l'appelle avec un nom de répertoire inexistant (ou un nom de fichier!), le script affiche un message d'erreur et termine avec le code de retour 2.

Solution:

#!/bin/bash

fichiers=0
dossiers=0

if [ $# -ne 1 ]; then
    echo "Usage:  $0 repertoire"
    exit 1
fi

if [ ! -d $1 ]; then
    echo "$1 n'est pas un repertoire valide"
    exit 2
fi

for OBJET in `ls $1`; do
    if [ -f $1/$OBJET ]; then
        let fichiers=fichiers+1
    elif [ -d $1/$OBJET ]; then
        let dossiers=dossiers+1
    fi
done

echo "Le repertoire $1 contient $fichiers fichiers et $dossiers sous-repertoires"


Le script est assez simple, on élimine les deux cas d'erreurs, puis on fait une boucle for qui passe à travers le contenu du répertoire passé en paramètre. Pour chaque item, on vérifie si c'est un fichier ou un répertoire et on incrémente le compteur approprié. À la fin, on affiche le résultat du décompte.

La seule chose à ne pas oublier: la boucle for fait un ls de $1, le répertoire voulu. La commande ls est remplacée par sa sortie, qui est une suite de noms de fichiers/dossiers tout simples. Lorsque l'on teste si l'un d'entre eux est un fichier ou un répertoire, on doit faire [ -f $1/$OBJET ] et non pas [ -f $OBJET ]. En effet, cette dernière façon de faire testerait l'existence de $OBJET dans le répertoire courant, celui où se trouve le script. Même si on est dans une boucle for qui a fait un ls de $1, rien n'indique à bash qu'on doit vérifier l'existence de ces fichiers dans $1. Il faut donc le faire explicitement nous-même.

Retour à la table des matières de la section

7.2 - Le créateur de HTML

Créez un script qui parcourt un répertoire contenant des images jpg (vous pouvez en trouver quelques-unes au hasard sur Internet pour en créer un si vous n'en avez pas sur votre système). Le script devra produire un fichier HTML qui contiendra une énumération de liens. Cliquer sur un des liens affichera l'image correspondante.

On devra lancer le script avec deux paramètres: le nom du répertoire contenant les images et le nom du fichier HTML à créer (sans l'extension .html).

Par exemple, si j'ai un répertoire $HOME/images qui contient les images image1.jpg à image5.jpg et que j'appelle mon script ainsi:

createurHTML $HOME/images fichier

Il créera un fichier appelé fichier.html qui contiendra des liens vers les images 1 à 5.

Comme d'habitude, vous devez valider le nombre de paramètres et l'existence du répertoires d'images avant d'aller plus loin.

Il faut évidemment avoir quelques bases de HTML:

Il ne faut pas non plus oublier que le guillemet est un caractère réservé en bash, puisqu'il sert à délimiter des chaînes. Si on veut écrire un guillemet sans qu'il ne soit pris pour un délimiteur, il faut le préfixer d'un backslash ainsi: \"

Solution:

#!/bin/bash

rm -f $2.html 2> /dev/null

for FICHIER in `ls $1`; do
    echo "<a href=\"$1/$FICHIER\">$FICHIER</a><br />" >> $2.html
done

Un bel exemple de script très simple et efficace, mais à la syntaxe rébarbative pour le non-initié! Le script contient une simple boucle qui passe dans le répertoire donné et qui écrit une ligne dans un fichier pour chaque fichier trouvé dans le répertoire.

La ligne ainsi créée:

<a href="repertoire/fichier">fichier</a><br />

Autrement dit: affiche le nom du fichier, et lorsqu'on clique dessus, amène nous au fichier, avec son chemin complet.

Notez que le fichier html ainsi créé correspond au deuxième paramètre, et il est effacé avant de commencer (pour éviter d'y ajouter d'une exécution à l'autre). Le -f du rm force la supression sans demander de confirmation et la redirection des messages d'erreur dans /dev/null évite d'afficher un message d'erreur à l'écran si le fichier n'existe pas.

Retour à la table des matières de la section

7.3 - Une nouvelle version de notre créateur d'usagers

Muni de toutes vos nouvelles connaissances, modifiez votre script CreerUsager afin de:

Solution:

#!/bin/bash

# $1 = nom du groupe, $2 = nom de l'usager, $3 = mot de passe

IFS=":"
GROUPEXIST=0

if [ $# -eq 3 ]; then
  while read USER RESTE; do
    if [ "$USER" == "$2" ]; then
      echo "$2 existe déjà"
      exit 2
    fi
  done < /etc/passwd
  
  while read GROUPNAME RESTE; do
    if [ "$GROUPNAME" == "$1" ]; then
      GROUPEXIST=1
      break
    fi
  done < /etc/group
  
  if [ $GROUPEXIST -ne 1 ]; then
    echo "Le groupe $1 sera cree"
    ./CreerGroupe $1
  fi
  
  /usr/sbin/useradd -g $1 -d /home/$1/$2 -m -s /bin/bash $2
  echo "$2:$3" > /usr/bin/chpasswd
else
  echo "Usage:  $0 groupe usager mot_de_passe"
  echo "groupe = nom du groupe principal de l'usager"
  echo "si groupe n'existe pas, il sera cree"
fi

On commence par faire une boucle qui lit le fichier d'usagers (/etc/passwd). Notez qu'on n'a réellement besoin que du premier champ, avec le nom de l'usager, alors il n'est pas nécessaire de séparer en 8 colonnes... Le nom de l'usager et le reste fera bien l'affaire! Si on tombe sur un nom qui correspond à celui que l'on tente de créer, c'est qu'il existe déjà, alors on affiche un message d'erreur et on sort.

Si on n'est pas sorti, on doit créer l'usager, alors on commencera par faire une boucle qui lit le fichier de groupes (/etc/group) à la recherche du groupe demandé. Encore une fois, on ne veut réellement que la première colonne, inutile de séparer tout le reste. Si on tombe sur le groupe voulu, on garde un flag pour se rappeler que le groupe existe déjà et on sort de la boucle avec un break (inutile de continuer à lire le fichier). Une fois sorti de la boucle, si notre flag n'a pas été levé, c'est que le groupe n'existe pas, alors on le crée.

On n'oublie pas de mettre notre flag à 0 en commençant, ni de changer IFS pour ":" puisqu'on lit des valeurs séparées par des ":" et non des espaces dans les deux fichiers.

Tout le reste est pareil comme lors du labo 2.

Retour à la table des matières de la section