Si vous redéposez: avant le jeudi 5 février, 18h00. |
Cette page sera mise à jour. Il convient d'en vérifier les informations de temps en temps, notamment avant la remise du DM. 50(Dernière mise à jour le4 janvier 2006)
find
mais également l'écriture d'une bibliothèque OCaml
fournissant les fonctionnalités de find
aux programmes OCaml.find
demandée. find
d'Unix (man find
) permettant d'exécuter les opérations
suivantes:
mon_find0
équivalente à find . -maxdepth 1
.
mon_find1
qui prend en argument une
profondeur p et affiche la liste des chemins accessibles depuis le
répertoire courant avec une profondeur inférieure à p.
-maxdepth
,
-type
,
-atime
,
-follow
,
-regexp
.
Arg
pour
récupérer les arguments de la ligne de commande et le module Str
(à
charger explicitement) pour manipuler les expressions régulières.-atime
, le
find
prend ses arguments sur la ligne de commande.
Tous ses arguments sont des chaînes de caractères qu'il faut interpréter.
En fait, elle prend deux types d'arguments : des options et un ensemble de
chemins qui sont les racines à partir desquels mener la recherche. type filter =
Maxdepth of int
| Type of Unix.file_kind
| Follow
| Regexp of Str.regexp
| Atime of interval
| Predicate of (string -> bool)
and interval =
Le of int | Eq of int | Ge of int |
follow
demande de suivre les liens symboliques, ce qui
n'est pas le cas par défaut. En présence de l'option -follow
on
gardera trace (de l'identité) des répertoires déjà visités de façon à ne pas
les visiter plusieurs fois: lorsqu'un lien symbolique mène à un répertoire
déjà visité, on affichera le lien mais on ne le suivra pas. intervalle
permet de représenter des valeurs respectivement
«inférieure ou égale» (Le
), égale (Eq
), et supérieure ou égale
(Ge
) à l'entier donné en argument. L'unité de temps est 24 heures.
La commande Unix find
utilise −n, n et +n pour spécifier
respectivement les valeurs (Le n), n et (Ge n).
En fait, find
utilise des inégalités strictes, mais nous utiliserons
des égalités larges (incluant l'égalité) ici, afin de rester compatible avec
les versions précédentes du sujet.
Predicate
prend en argument une fonction qui est
appliquée au chemin et qui indique s'il faut garder ce chemin (à la manière
de Regexp
). Par exemple,
Predicate (fun d -> Sys.file_exists (Filename.concat d "CVS")) |
CVS
(i.e. les répertoires qui
contiennent un sous-répertoire CVS
)1.mode
suivant:
type mode =
| Ignore
| Stderr
| Failure
| Custom of (Unix.error * string * string -> unit) |
Ignore
, les erreurs sont simplement ignorées et le calcul
de find sur le reste de la hiérarchie est poursuivi. Le mode Stderr
fonctionne comme le mode
Ignore
à part qu'il imprime un message d'erreur sur la sortie
d'erreur. Dans le mode Failure
, le calcul est abandonné dès la
première erreur et elle est reportée immédiatement à l'utilisateur. Le mode
Custom
utilise la fonction fournie au constructeur pour traiter
l'erreur.find
n'est plus une commande Unix, mais une fonction de
bibliothèque, il n'est plus nécessaire de retourner les résultats dans la
sortie standard (typiquement le terminal), et il est préférable de les
retourner en mémoire, par exemple dans une liste. Mieux, on peut abstraire
la fonction par rapport à ce que l'on veut faire sur les résultats,
par exemple
comme le fait la fonction List.iter
dans un parcours de liste. find
aura le type suivant:
val find : mode -> string list -> filter list ->
(string -> unit) -> unit |
find
m r p f recherche récursivement les chemins issus d'une
des racines r satisfaisant les filtres p et applique f au fur et à
mesure que les chemins sont trouvés. find Stderr [ "." ] [] print_endline |
find .
». Custom
pour collecter
l'ensemble des messages d'erreurs par exemple en les cumulant dans une
référence. find.ml
satisfaisant l'interface find.mli
et la sémantique décrites ci-dessus.mon_find
de la question 4) de l'exercice ci-dessus en utilisant la bibliothèque
find.ml
. Le programme mon_find
ne reconnaît donc que
les options de la question 4) de l'exercice. En particulier n'a pas
d'option équivalente à l'option Predicate
de la librairie.
De même, le mode de fonctionnement de la commande mon_find
n'est pas
passé en argument et correspond au mode Stderr
.find.ml
et un fichier mon_find.ml
dans un répertoire ayant comme nom votre login.find.ml
devra respecter l'interface
find.mli.mon_find.ml
devra permettre de fabriquer le programme
mon_find
par la ligne de commande:
ocamlc -o mon_find unix.cma str.cma find.mli find.ml mon_find.ml |
cd /users/profs/info/INF552 |
./deposer-DM1 <chemin>/find.ml <chemin>/mon_find.ml |
./deposer-DM1 |
find.mli
, vous devrez
changer intervalle
en interval
si vous avez encore une ancienne
version de find.mli
(récupérez la version ci-dessus).Sys
avant le module Unix
ou écrivez Unix.readdir
au lieu readdir
en raison de l'ajout
d'une fonction readdir
dans le module Sys
.
tar -z -xvf arch.tar.gz
.find
de Unix. Il n'y a pas de raison, a
priori, pour que la sortie diffère de celle de find
pour les tests du
groupe 1 ci-dessous. Pour les tests du groupe 2, vous pouvez éventuellement,
pour certains tests, trouver moins de chemin que la commande find
.
Pour les tests du groupe 3, vous pouvez éventuellement reporter les erreurs
différement, mais pas réussir sans repport d'erreur lorsque l'autre échoue
ou inversement (sur les tests donnés) et vous devez a priori trouver au
moins trouver les fichiers trouvés par la commande Unix.
Pour les tests du groupe 4, vous devez repporter proprement
les erreurs d'analyse de la ligne de commande et ne pas laisser une
exception non rattrappée.stdout
! N'imprimez dans
stderr
que les messages d'erreurs, par d'information de mise au point,
pas de commentaires inutile, de façon concise, (si possible comme le fait
find).Predicate
, Custom
et en changeant la
fonction de traitement). Les test 1 à 3 ci-dessous peuvent se faire
avec find.ml
sans utiliser mon_find.ml
en faissant simplement
des appels directs à la fonction find
.find.ml
doit reporter des erreurs en levant
des exceptions, surtout pas appeler directement exit
(sauf pour une
assertion invalide, i.e. repporter un bug du programme, qui ne devrait donc
jamais être levée).Test | Command |
1. Tests simples (sans -follow) | |
Order on single entry | find B |
Order on multiple entries | find B/a B/b |
Default on whole directory | find A B |
Type regular | find A -type f |
Maxdepth 1 | find A -maxdepth 1 |
Combine options | find A -maxdepth 2 -type f |
Regex left | find B -regexp '@@A' |
Regex right | find B -regexp 'B/@' |
Type regular and regexp | find B -type f -regexp 'B/[ab]' |
2. Tests avec -follow | |
Follow (simple) | find D -follow |
Follow with multiple entries | find C D -follow |
Follow (self recursion) | find A -follow |
Follow and links | find A -follow -type l |
Not follow and links | find A -type l |
3. Tests avec erreurs | |
Innaccessible link (ok) | find 'E/@?' |
Innaccessible link (fail) | find 'E/@?' -follow |
Unreadable directory (fail) | find E/R |
Directory execution missing (fail) | find E/X |
4. Analyse de la ligne de commande | |
Comparaison avec la librairie | find A |
Inversion des entrées? | find B/a B/b |
Appel sans arguments | find |
Option non reconnue | find B/a -foo |
Argument incorrect | find B/a -type a |
Argument vide | find B/a -maxdepth '' |
Argument vide | find B/a -atime '' |
find.ml
en appelant directement la librairie depuis un programme OCaml.
Les tests du groupe 4 testent essentiellement le programme mon_find.ml
.Ne déposer pas votre programme s'il ne passe les tests! Débugger le d'abord. Demandez de l'aide en TD.Faites le dépôt avant: Jeudi 5 février, 18h.
group
est une lettre en A et E qui résume la catégorie dans
laquelle se situe votre programme en «l'état» et ne dépend que de l'ensemble
des tests effectués:
A: | C'est très bien. |
B: | Il y a un petit problème, sûrement facile à corriger |
C: | Il y a, a priori, des problèmes avec le traitement des liens |
D: | Il y a des problèmes sérieux ou sur de nombreux types de chemins |
E: | Le programme ne compile |
find.ml
en appelant directement la librairie (donc sans utiliser votre fichier
mon_find.ml
). En ce sens les tests effectués sont plus fins et peuvent
différés des tests que vous auriez effectués avec mon_find.ml
en
regardant la sortie standard ou d'erreur. En particulier, les derniers tests,
provoquent une exception pendant le traitement de action appliquée à un
chemin filtré.X: | Appel à exit pendant l'exécution du test |
L: | Boucle ou Blocage du programme |
R: | Retour de l'appel (exception levée) |
S: | Statut du retour (erreurs reportés ou non) |
E: | Ensemble des erreurs reportées |
I: | Ensemble des inodes (au bout des chemins) trouvés incorrects |
-: | Chemin manquant |
+: | Chemin trouvé en trop |
a: | Aucune erreur |
mon_find.ml
, mais sans utiliser
votre find.ml
: vous pouvez donc passer les seconds tests même avec des
erreurs dans find.ml.Groupe | A | B | C | D | E | total |
Nombre | 9 | 7 | 10 | 16 | 2 | 44 |
mon_find
devait être non nul lorsqu'il
y a eu des erreurs pendant le parcours.
-regexp
r demande de filtrer exactement le chemin: il faut
donc que le filtre r puisse s'applique au tout début du chemin et se
terminer à la fin.
exit
dans la librairie! ni
directement, ni via un appel à handler_unix_error, y compris
dans le mode Failure
.
Filename
(et pas .
et ..
) directement pour
être portable. Seulement 1/4 d'entre vous l'on bien fait!
let body() =
let resource = alloue ...
let rec treat f x =
try ... treat g y ... with x -> libère resource; raise x in
treat f x |
Unix_error
, celle-ci doit arrêter l'appel sans passer par le
traitement des chemins erronés. exception Hide_exn of exn;;
let hide_exn f x = try f x with exn -> Hide exn;;
let reveal_exn f x = try f x with Hide exn -> raise exn;;
let unprotected_find args... action = ...
let find args... action =
reveal_exn (unprotected_find args...) (hide_exn action) |
Custom
.
Cela peut également être utiliser pour traiter l'option Failure
.
L'exception encapsulée sera vue comme une exception ordinaire,
provoquant au retour des appels récursifs le code de finalisation
(fermeture des répertoires ouverts) et non son traitement comme une erreur
de parcours Unix_error
sur le répertoire courant. Ce document a été traduit de LATEX par HEVEA