CSC 3102 – Introduction aux systèmes d’exploitation

Portail informatique

TP4 – Chasse au trésor

Pour faire les exercices, vous avez besoin de connaître le langage bash. Vous pouvez vous référer à l'annexe shell. Vous pouvez aussi trouver une liste d'astuces ici. Tous les exercices sont obligatoires, sauf les exercices notés « défi » ou « optionnel » qui sont optionnels. En particulier, les exercices notés « hors présentiel » sont supposés fait d'une séance sur la suivante.

Trouver un trésor et, accessoirement, réviser toutes les notions de CSC3102 vues jusqu'à présent.

Voici l'ultime trace du trésor confié à Bilbon lors de l'un de ses longs voyages itinérants de la fin du XXè siècle.

« Face à la clé du trésor cachée dans les itinéraires signés de mes nombreux voyages à travers de vastes pays de la fin du siècle dernier, l'anagramme des premières lettres des trois premières lignes selon l'ordre alphabétique portant le mot "à" en garantira l'authenticité. La clé ainsi découverte, il vous faudra la réorganiser selon un ordre lexicographique de troisième champ afin d'en extraire les 3è mots des couples de lignes de tête et de queue de lignes, et ainsi découvrir le chemin jusqu'au trésor ! »

Mise en place de la chasse au trésor (∼5mn)

Récupérez l'archive des carnets de voyage de Bilbon en utilisant la commande wget.
$ wget http://www-inf.telecom-sudparis.eu/COURS/CSC3102/Supports/ci4-outils/exo-chasse-au-tresor/CarnetsDeVoyage.tar.gz
Si vous êtes sous MacOS, la command wget n'est pas installée par défaut. En remplacement, utilisez curl comme ci-dessous :
$ curl http://www-inf.telecom-sudparis.eu/COURS/CSC3102/Supports/ci4-outils/exo-chasse-au-tresor/CarnetsDeVoyage.tar.gz --output CarnetsDeVoyage.tar.gz

Extrayez l'archive.
$ tar -zxvf CarnetsDeVoyage.tar.gz

Identification du voyage (∼1h10)

Identifier le répertoire dans lequel se trouve la clé du trésor.

La clé du trésor est cachée au sein d'un des répertoires de l'archive extraite. Chacun des répertoires correspond à un voyage, dont chacun des noms a été construit sur le même modèle : <année>-<lieu>, associé aux date et destination du voyage entrepris. Le champ année est toujours constitué de quatre chiffres. Quant au champ lieu, il correspond soit à un pays, et dans ce cas il commence par une majuscule, soit à une ville et il commence par une minuscule. Les deux champs sont séparés soit par un tiret haut, soit par un tiret bas.

La clé du trésor ayant été cachée lors d'un voyage itinérant à la fin du siècle dernier, nous sommes à la recherche d'un répertoire dont la date de création est comprise entre 1970 et 1999, et dont le lieu référence un pays. Par exemple, 1986-Bolivie.

Afin de mener à bien la recherche de la clé du trésor, nous vous proposons de procéder de manière incrémentale. Pour cela, vous allez écrire un script nommé chasse.sh que vous modifierez à chaque étape.

À chaque étape, pensez à vérifier que votre script est correct en l'exécutant.

Commencez par écrire le script nommé chasse.sh dans le répertoire courant (c.-à-d., le répertoire parent de CarnetsDeVoyage).

Ce script doit définir une variable nommée base, et lui affecter le chemin CarnetsDeVoyage.

Lancez votre script et vérifiez que votre script est correct en affichant cette variable à l'aide d'un echo.
Dans toute la suite de l'exercice, nous supposons que votre répertoire courant est le répertoire parent de CarnetsDeVoyage.
$ ./chasse.sh CarnetsDeVoyage

Votre script doit maintenant sélectionner tous les fichiers qui correspondent à des voyages. En procédant étape par étape et en utilisant des motifs de filtrage bash, modifiez la commande echo de la question précédente pour afficher :
  • tous les fichiers dont le nom commence par 19 se trouvant dans le répertoire $base,
  • tous les fichiers dont le nom commence par 19 et est suivi par un chiffre entre 7 et 9,
  • tous les fichiers dont le nom commence par 19, est suivi par un chiffre entre 7 et 9, et est suivi d'un chiffre quelconque,
  • tous les fichiers dont le nom commence par 19, est suivi par un chiffre entre 7 et 9, est suivi d'un chiffre quelconque, et est suivi soit par un tiret bas soit par un tiret haut.
  • tous les fichiers dont le nom commence par 19, est suivi par un chiffre entre 7 et 9, est suivi d'un chiffre quelconque, est suivi soit par un tiret bas soit par un tiret haut, et est suivi d'une chaîne de caractères quelconque dont la première lettre est une majuscule.

Pour vous aider, vous devriez écrire une commande du type
echo $base/[un-motif-ici]
Vérifiez manuellement que les entrées sélectionnées correspondent bien aux descriptions données.
$ ./chasse.sh CarnetsDeVoyage/1972-Australie CarnetsDeVoyage/1978-Senegal CarnetsDeVoyage/1982_France CarnetsDeVoyage/1998-Belgique.txt

À ce stade, il doit vous rester 4 entrées candidates car il n'y a eu aucun filtre sur le type des entrées considérées.

Nous sommes à la recherche d'un plan d'itinéraire. Nous pouvons donc raffiner notre quête en nous limitant aux répertoires dans lequel le trésor aura possiblement été caché. Avant de vérifier si un fichier est un répertoire, votre script doit d'abord itérer sur les noms trouvés à la question précédente.

Au lieu d'afficher les noms trouvés avec un echo, votre script doit donc itérer sur les noms trouvés avec un for, et les afficher chacun sur une ligne. Le schéma d'algorithme est le suivant :
for x in motif-bash-question-précédente; do echo $x done
$ ./chasse.sh CarnetsDeVoyage/1972-Australie CarnetsDeVoyage/1978-Senegal CarnetsDeVoyage/1982_France CarnetsDeVoyage/1998-Belgique.txt

Modifiez le corps de la boucle de façon à n'afficher que les répertoires.
$ ./chasse.sh CarnetsDeVoyage/1972-Australie CarnetsDeVoyage/1978-Senegal

Le voyage ayant été long, votre script doit sélectionner le répertoire le plus volumineux. Vous devez donc modifier votre boucle de façon à stocker, dans une nouvelle variable nommé rep, le répertoire le plus volumineux. Nous procédons en plusieurs étapes. Dans un premier temps, remplacez le echo de la question précédente de façon à afficher la taille de chacun des répertoires. Pour ne pas afficher la taille des sous-répertoires, pensez à utiliser l'option -d0 de du.
$ ./chasse.sh 44 CarnetsDeVoyage/1972-Australie 268 CarnetsDeVoyage/1978-Senegal

En utilisant un tube et la commande cut, n'affichez que la taille des répertoires (c.-à-d., sans leur nom).
$ ./chasse.sh 44 268

Stockez cette taille dans une variable que vous appellerez cur, puis affichez cur avec echo. Pensez à utiliser une imbrication de commandes, c.-à-d., la construction $(...). Votre affichage doit être similaire à celui de la question précédente.
$ ./chasse.sh 44 268

Stockez dans la variable nommée rep le répertoire le plus volumineux et affichez le après la boucle. Pour cela, nous vous proposons d'utiliser l'algorithme suivant capable de trouver le répertoire le plus volumineux :
size prend la valeur 0 Pour tout x correspondant au motif Si x est un répertoire cur prend la taille du répertoire x Si size plus petit que cur size prend la valeur de cur rep prend la valeur de x FinSi FinSi FinPour Affiche rep
Si la variable rep est égale à la chaîne de caractères vide, c'est que quelque chose s'est mal passé pendant votre chasse.
$ ./chasse.sh CarnetsDeVoyage/1978-Senegal
Bravo ! Vous avez découvert le voyage qui héberge la clé du trésor !

Identification de la clé du trésor (∼30mn)

Trouver le fichier qui sert de clé au trésor !

Pour identifier le fichier qui sert de clé, nous procédons étape par étape. Commencez par étendre le script chasse.sh pour afficher tous les fichiers ordinaires se trouvant dans le répertoire $rep ou dans un de ses sous-répertoires, et dont le nom contient "Itineraire".

À cette question, il ne faut pas utiliser de recherche par motif comme vous l'avez fait au début de l'exercice 2. En effet, une recherche par motif cherche des fichiers dans un répertoire mais pas dans les sous-répertoires. À cette question, il faut donc utiliser la commande find qui permet de chercher des fichiers dans un répertoire et dans ses sous-répertoires. On vous rappelle que pour trouver des fichiers ordinaires, il faut utiliser l'option -type f de find.
$ ./chasse.sh CarnetsDeVoyage/1978-Senegal/Itineraire_retenu.txt CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire.txt CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire_bis.txt

Comme nous devons accéder au contenu de chacun des fichiers trouvés, nous devons itérer sur les fichiers trouvés à la question précédente. Commencez par faire une boucle for pour itérer, avec une variable x, sur chacun de ces fichiers (pensez à utiliser la construction $(...) pour récupérer la sortie produite à la question précédente). Dans le corps de cette boucle for, affichez le nom du fichier sur une ligne avec la commande echo. L'affichage produit doit être similaire à celui de la question précédente.
$ ./chasse.sh CarnetsDeVoyage/1978-Senegal/Itineraire_retenu.txt CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire.txt CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire_bis.txt

Dans le corps de la boucle, au lieu d'afficher le nom du fichier, cherchez dans le fichier la signature de son auteur, c.-à-d. « Bilbon », avec la commande grep.
$ ./chasse.sh Voyage itinérant 2015-Seychelles de Bilbon : de Mahe à La Digue

Au lieu d'afficher la ligne correspondant au motif « Bilbon », affichez le nom du seul fichier ayant pour signature Bilbon. Pour vous guider, il faut savoir qu'avec l'option -q, on peut demander à grep de ne rien afficher du tout, mais plutôt de terminer avec un code de retour vrai dès qu'elle trouve une ligne qui correspond au motif. En d'autres termes, vous pouvez utiliser un code similaire à celui-ci :
if grep -q motif fichier; then ... fi
$ ./chasse.sh CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire.txt

Le but de cette question est de résoudre une première partie de l'énigme : « l'anagramme des premières lettres des trois premières lignes selon l'ordre alphabétique portant le mot "à" en garantira l'authenticité ». Au lieu d'afficher le fichier trouvé comme à la question précédente, utilisez des tubes pour chaîner les commandes suivantes :
  • affichez, avec la commande grep, toutes les lignes contenant le caractère « à » dans le fichier,
  • triez, avec la commande sort, ces lignes en suivant l'ordre lexicographique,
  • ne gardez que les trois premières lignes du fichier avec la commande head,
  • ne gardez que la première lettre de chaque ligne avec la commande cut,
  • supprimez les retours à la ligne avec la commande tr (caractère « \n »);

Nous vous conseillons vivement de procéder étape par étape.

Si Bilbon ne se moque pas de vous, vous devriez obtenir un anagramme du mot « CLE ». Remarquez que, comme vous avez trié les lignes en suivant l'ordre lexicographique, cet anagramme ne peut être que « CEL ».
$ ./chasse.sh CEL

Lorsque vous trouvez le fichier contenant l'anagramme du mot « CLE », vous devez stocker le nom de ce fichier dans une variable nommée cle. Pour vous assurer que votre script est correct, affichez la valeur de cette variable à la fin du script. Si votre script est correct, il devrait vous afficher le fichier contenant l'anagramme du mot « CLE ».
$ ./chasse.sh CarnetsDeVoyage/1978-Senegal/Organisation/Itineraire.txt
Bravo ! Vous avez identifié le fichier contenant la clé !

Ultime étape : la découverte du trésor ! (∼45mn)

Maintenant que vous avez identifié le fichier contenant la clé du trésor, vous allez (enfin !) pouvoir trouver le trésor.

Nous vous rappelons que la fin de l'énigme est : « La clé ainsi découverte, il vous faudra la réorganiser selon un ordre lexicographique de troisième champ afin d'en extraire les 3è mots des couples de lignes de tête et de queue de lignes, et ainsi découvrir le chemin jusqu'au trésor ! »

Nous commencons par trier le fichier stocké dans la variable cle selon un ordre lexicographique de troisième champ. Dans le script chasse.sh, remplacez l'affichage de la variable cle par l'affichage du fichier cle, trié selon le troisième champs de chaque ligne (avec l'option -k de sort).
Par défaut, la commande sort de Linux ignore la casse, mais ce n'est pas le cas sur un MacOS. Pour cette raison, les utilisateurs de MacOS doivent ignorer la casse en utilisant l'option -f.
$ ./chasse.sh Voyage itinérant 2015-Seychelles de Bilbon : de Mahe à La Digue Ile principale Mahe puis Praslin et La Digue J1 : Mahe Grottes le matin J4 : opération plongée Ne pas oublier corde à sauter Souvenirs indispensables pagaie coquillages Vanille La plus paisible : à l'ouest de la ville Voiture à parquer sur l'espace surveillé J2 : Paslin Equipement à payer au centre de loisir Cascade à pied J5 : pirogue jusqu'au dessus de l'épave Plus belles Plages autour : au sud Plus belles Plages de l'île : nord et sud J5 : relache

« [...] extraire les 3e mots des couples de lignes de tête et de queue de lignes [...] ». Pour réussir à résoudre cette partie de l'énigme, nous vous proposons de :
  • Eliminez les lignes vides : Pour ce faire, filtrez le résultat de la commande précédente de façon à ne conserver que les lignes qui contiennent du texte (sachez que le motif . de grep, permet de capturer n'importe quel caractère).
  • Sauvegardez ce résultat dans un fichier nommé Itineraire_trie.txt.
  • Isolez les deux premières lignes du fichier Itineraire_trie.txt et sauvegardez-les dans un fichier nommé Itineraire_trie_compact.txt.
  • Isolez les deux dernières lignes du fichier Itineraire_trie.txt et ajoutez-les au fichier nommé Itineraire_trie_compact.txt.
  • Stockez dans une variable nommée mots les troisièmes mots de chacune des lignes de Itineraire_trie_compact.txt.
  • Supprimez les fichiers Itineraire_trie.txt et Itineraire_trie_compact.txt.
  • Enfin, affichez le contenu de la variable mots.

Nous vous conseillons de procéder étape par étape et de vérifier, à chaque étape, que votre code fonctionne correctement.
$ ./chasse.sh 2015-Seychelles Mahe Plages relache

Afin d'afficher le trésor, il faut d'abord reconstituer le chemin vers le trésor dans une variable nommée tresor. Pour cela, il faut ajouter des « / » entre les différents mots de la variable mots. Au lieu d'afficher la variable mots, nous vous proposons donc l'algorithme suivant :
tresor prend la valeur de la variable base Pour tout mot dans mots ajouter '/' et mot à la fin de tresor FinPour Afficher la variable tresor
$ ./chasse.sh CarnetsDeVoyage/2015-Seychelles/Mahe/Plages/relache

Ultime étape ! Au lieu d'afficher le chemin du trésor, affichez son contenu.
$ ./chasse.sh ,gaaaaaaaagaaaaaaaaaaaaagaaaaaaaag, ,aP8b _,dYba, ,adPb,_ d8Ya, ,aP" Yb_,dP" "Yba, ,adP" "Yb,_dP "Ya, ,aP" _88" )888( "88_ "Ya, ,aP" _,dP"Yb ,adP"8"Yba, dP"Yb,_ "Ya, ,aPYb _,dP8 Yb ,adP" 8 "Yba, dP 8Yb,_ dPYa, ,aP" YdP" dP YbdP" 8 "YbdP Yb "YbP "Ya, I8aaaaaa8aaa8baaaaaa88aaaaaaaa8aaaaaaaa88aaaaaad8aaa8aaaaaa8I `Yb, d8a, Ya d8b, 8 ,d8b aP ,a8b ,dP' "Yb,dP "Ya "8, dI "Yb, 8 ,dP" Ib ,8" aP" Yb,dP" "Y8, "YaI8, ,8' "Yb, 8 ,dP" `8, ,8IaP" ,8P" "Yb, `"Y8ad' "Yb,8,dP" `ba8P"' ,dP" "Yb, `"8, "Y8P" ,8"' ,dP" "Yb, `8, 8 ,8' ,dP" "Yb, `Ya 8 aP' ,dP" "Yb, "8, 8 ,8" ,dP" "Yb, `8, 8 ,8' ,dP" Normand "Yb, `Ya 8 aP' ,dP" Veilleux "Yb, "8, 8 ,8" ,dP" "Yb,`8, 8 ,8',dP" "Yb,Ya8aP,dP" "Y88888P" "Y8P" "
Bravo ! Vous avez découvert le trésor !