La programmation en Perl
Jean-Philippe Peyrache
Université Jean Monnet - Faculté des Sciences et Techniques Licence Informatique - Semestre 5
Plan du cours
1 Introduction générale 2 Les variables scalaires 3 Autres types de variables 4 Conditionnelles et boucles 5 Les expressions régulières
6 Travailler avec des entrées/sorties 7 Divers
Introduction générale
Introduction générale
Le langage Perl
Le langage Perl a pour but de simplifier la mise en oeuvre des tâches simples tout en autorisant la programmation de tâches compliquées. Caractéristiques :
Langage interprété
Portabilité (sous certaines conditions)
Possibilité de Pattern Matching (expressions régulières) Manipulation de répertoires, fichiers, processus
Introduction générale
Le langage Perl
Domaines d’utilisation : Scripts divers
Administration système
Extension de ligne de commande . . .
Introduction générale
Se renseigner sur Perl
Documentation complète à l’aide de “man perl”
Information sur la syntaxe d’une fonction à l’aide de “perldoc -f nom_fonction”
FAQ : http://www.perl.com/perl.faq
Modules et documentations : http://www.perl.com/perl/ ou http://www.perl/org
Introduction générale
Format d’un script Perl
Fichier avec extension pl #!/usr/local/bin/perl -w # Script de démonstration
$nom = "Jean Durant"; # Initialisation de la variable $nom $age = 30; # Initialisation de $age
$age++; # Incrémentation
$aImprimer = "L’âge de $nom est $age \n"; # Concaténation print $aImprimer; # Impression
Introduction générale
Format d’un script Perl
Un script Perl contient :
Une première ligne indiquant au shell l’emplacement de l’interpréteur Perl.
Des lignes de commentaires (débutant par “#”). Des instructions.
Une instruction se termine par un “;”. Un bloc est un ensemble d’instructions délimité par des accolades.
Les variables scalaires
Les variables scalaires
Types de variables
Les variables scalaires sont les briques de base du langage, elles sont de deux types :
Type numérique Type chaîne
Les variables scalaires
Opérateurs numériques
Opération Syntaxe Résultat
Egal à $a == $b Vrai/Faux
Différent de $a != $b Vrai/Faux
Inférieur (ou égal) à $a < (<=) $b Vrai/Faux
Supérieur (ou égal) à $a > (>=) $b Vrai/Faux
Comparaison $a <==> $b 0 / 1 / -1
Plus $a + $b Somme de a et b
Incrémentation $a++ (ou ++$a) Auto-incrémentation
Décrémentation $a−− (ou −−$a) Auto-décrémentation
Multiplication $a * $b Produit de a et b
Modulo $a % $b Reste de a divisé par b
Puissance $a ** $b a puissance b
Et $a && (ou and) $b Vrai/Faux
Ou $a || (ou or) $b Vrai/Faux
Les variables scalaires
Opérateurs pour chaînes
Opération Syntaxe Résultat
Egal à $a eq $b Vrai/Faux
Différent de $a ne $b Vrai/Faux
Inférieur (ou égal) à $a lt (ou le) $b Vrai/Faux
Supérieur (ou égal) à $a gt (ou ge) $b Vrai/Faux
Comparaison $a cmp $b 0 / 1 / -1
Incrémentation $a++ (ou ++$a) Auto-incrémentation
Décrémentation $a−− (ou −−$a) Auto-décrémentation
Concaténation $a . " est un " . $b Chaîne concaténée
Multiplication $a x 6 Répétition de concaténation
Longueur length $a Longueur de $a
Et $a && (ou and) $b Vrai/Faux
Ou $a || (ou or) $b Vrai/Faux
Les variables scalaires
Informations
Les opérateurs logiques sont des opérateurs court-circuits. Les affectations raccourcies sont autorisées :
$a += $b; $a *= 3; $c .= ";";
Une variable scalaire est fausse si :
Elle est de type chaîne et est égale soit à "", soit à "0". Elle est de type nombre et est égale à 0.
Elle est indéfinie (a pour valeur undef ).
La fonction defined $a permet de savoir si la variable scalaire $a est définie ou non.
Les variables scalaires
Caractères spéciaux
Pour insérer des guillemets à l’intérieur d’une chaîne, deux possibilités : "\"Arrêtez !\", dit-il."
’"Arrêtez !", dit-il.’
D’autres caractères spéciaux existent : "\\" −→ \
"\n" −→ Saut de ligne "\t" −→ Tabulation . . .
Les variables scalaires
Exemples
$un_fruit = "une pomme";
print "Hier, j’ai mangé $un_fruit.\n"; print ’Hier, j\’ai mangé $un_fruit.\n’; Hier, j’ai mangé une pomme.
Hier, j’ai mangé $un_fruit.\n
Les variables scalaires
Exemples
$quatre = "4"; $deux = "2";
$quatre_et_deux = $quatre . $deux; # concaténation
$quatre_plus_deux = $quatre + $deux; # addition
$quatre_x_deux = $quatre x $deux; # répétition
$quatre_fois_deux = $quatre * $deux; # multiplication
print ’$quatre_et_deux = ’ . "$quatre_et_deux \n";
print ’$quatre_plus_deux = ’ . "$quatre_plus_deux \n";
print ’$quatre_x_deux = ’ . "$quatre_x_deux \n";
Les variables scalaires
Nouvelles instructions
print "Comment vous appelez-vous ? ";
$nom = <>; # Récupération du nom de l’utilisateur
chomp $nom; # Retrait du saut de ligne
print "Bonjour, $nom !\n";
Comment vous appelez-vous ? Obi-Wan Kenobi Bonjour, Obi-Wan Kenobi !
<> sert à lire une ligne dans un flux de données. Ici, il est équivalent à <STDIN>. chomp sert à retirer les sauts de ligne à la fin d’une chaîne(chop supprime le dernier caractère, quel qu’il soit). chop et chomp peuvent être appliquées sur des listes.
Les variables scalaires
Exercices
Ecrivez une fonction qui demande d’entrer une phrase, puis un nombre et qui recopie la phrase donnée le nombre de fois indiqué.
Ecrivez une fonction qui demande d’entrer un nombre et donne la table de multiplication de 1 à 10 correspondante.
Autres types de variables
Autres types de variables
Les tableaux (généralités)
Un tableau est une liste ordonnée de scalaires indicée par la position du scalaire dans la liste. Les variables de type tableaux (ou liste) se présentent sous la forme :
@utilisateur = ("roger","/home/roger/",1000,"/bin/tcsh") On accède aux éléments du tableau par des nombres ou par bloc : $nomUtilisateur = $utilisateur[0];
($login,$home,$uid,$shell) = @utilisateur;
L’indexation commence à 0. On utilise $ pour référencer un élément du tableau.
Autres types de variables
Les tableaux (initialisation)
Plusieurs méthodes : $utilisateur[0] = "roger"; $utilisateur[1] = "/home/roger"; $utilisateur[2] = 1000; $utilisateur[3] = "/bin/tcsh"; @utilisateur = ("roger","/home/roger/",1000,"/bin/tcsh"); @utilisateur1 = @utilisateur2; @utilisateur = f();
Autres types de variables
Opérations de base sur les tableaux
pop Tab : traite un tableau comme une pile. Elle dépile le dernier élément du tableau en diminuant sa taille de 1.
push Tab Liste : traite Tab comme une pile et empile les valeurs de Liste à la fin du tableau (dont la longueur augmente de celle de Liste). shift Tab : décale la première valeur du tableau et la renvoie, réduisant ainsi la taille du tableau. Si le tableau est vide, renvoie undef.
unshift Tab Liste : fait l’inverse de shift, en ajoutant au début du tableau les éléments de Liste et renvoie le nombre d’éléments dans le nouveau tableau.
Autres types de variables
Les tableaux (divers)
sort LIST permet de trier un tableau ou une liste selon plusieurs critères. On peut définir lors de l’appel la fonction de comparaison à utiliser entre les variables $a et $b.
# Tri dans l’ordre alphabétique
@UtilisateursTries = sort {$b cmp $a} @utilisateurs; # Tri par ordre numérique
@NumDeTel = sort {$a <=> $b} @tel;
On peut récupérer la taille d’un tableau @t de deux manières différentes : $nbElems = scalar @t;
Autres types de variables
Les tables de hachage (initialisation)
Un hachage hash est une liste d’éléments indexés par des chaînes. Une variable de type hachage a la forme %nomDuHachage.
Il y a plusieurs méthodes d’initialisation : %exam = (); # Initialisation à vide $exam{Durant} = 19; $exam{Brown} = 13; $exam{Schmit} = 18; %exam = ( Durant => 19, Brown => 13, Schmit => 18, ); %exam = ("Durant",19,"Brown",13,"Schmit",18);
Autres types de variables
Opérations de base sur les hachages
keys Hash : retourne les clés du hachage. @nom = keys %exam; values Hash : duale de la fonction keys. Elle renvoie les différentes valeurs du hachage dans un ordre aléatoire (dû au codage interne des hachages).
each Hash : retourne chaque paire (clé,valeur) du hachage. exists expr : renvoie vrai si la clé spécifiée existe dans le hachage. Attention, une clé peut être définie sans que la valeur correspondante ne le soit !
delete expr : détruit la clé et sa valeur correspondante. delete $MonHash{$MaCle}. On peut détruire tout un hachage de la façon suivante : undef %MonHash;
Conditionnelles et boucles
Conditionnelles et boucles
Les conditionnelles
if (condition 1){ instruction 1; }else{ instruction 2; }où les conditions sont n’importe quelle expression susceptible d’être interprétée comme une variable booléenne.
Conditionnelles et boucles
Les conditionnelles
if (condition 1){ instruction 1; }elsif(condition 2){ instruction 2; }elsif(condition 3){ instruction 3; }else{ instruction 4; }Conditionnelles et boucles
Les conditionnelles
unless($user eq "root"){ print $user;
}
Conditionnelles et boucles
Les structures de boucle
while($user ne "root"){ print $user; } until($user eq "root"){ print $user; }
until est la duale de while. La syntaxe de for est la même qu’en C. for($i=0;$i<=10;$i++){
print $i; }
Conditionnelles et boucles
Les structures de boucle
La boucle foreach parcourt une liste de valeurs et applique à chaque variable l’instruction indiquée.
foreach $elem (@MonTab){ $elem *= 2;
}
foreach $nom (keys %exam){ if ($exam{$nom} >= 10){
print $nom; }
}
Si aucun nom de variable n’est spécifié (i.e. foreach (LISTE), les éléments seront contenus dans la variable par défaut $_.
Conditionnelles et boucles
Exercices
Ecrivez une fonction qui tire un nombre entier aléatoire entre 0 et 100 (int (rand 101);) et qui vous répond si c’est plus ou moins à chacune de vos tentatives, jusqu’à ce que vous ayez trouvé.
Ecrivez une fonction qui entre dans un tableau les 100 premiers nombres premiers, puis affiche tous les éléments du tableau.
Créez une table de hachage pour gérer votre stock de vin, dans laquelle le nom du vin est utilisé comme clé, tandis que la quantité correspond à la valeur. Vous demanderez au début de la fonction combien de vins différents doivent être entrés dans le stock.
Les expressions régulières
Les expressions régulières
Quel intérêt ?
Les expressions régulières permettent d’écrire une expression qui représente plusieurs chaînes à la fois. On peut faire :
Du pattern matching, avec l’opérateur m// De la substitution, avec l’opérateur s//
L’opérateur de recherche m prend une chaîne et un motif en entrée et retourne VRAI si le motif appartient à la chaîne, FAUX sinon.
L’opérateur de substitution prend une chaîne et deux motifs. Il substitue le deuxième motif au premier et retourne le nombre de changements réalisés. On utilise toujours, pour récupérer le résultat de la fonction, l’opérateur =∼.
Les expressions régulières
Exemples
while($ligne = <STDIN>){ if($ligne =~ m/http:/){ print $ligne; } } while($ligne = <STDIN>){ $ligne =~ s/http:/ftp:/; print $ligne; }Les expressions régulières
Décrire un motif
Les opérateurs regardent si la chaîne présentée peut être parsée par le motif. Ils renvoient toujours le motif le plus grand et le plus à gauche.
Les motifs fonctionnent comme des chaînes entre doubles apostrophes. Les variables y sont interpolées.
Si une recherche de motif intervient dans une boucle, le motif est recalculé à chaque tour de boucle.
Les expressions régulières
Outils de description
Les répétitions :
∗ −→ un nombre quelconque de fois, éventuellement nul, de répétitions du caractère qui le précède.
+ −→ un nombre quelconque, non nul, de répétitions du caractère qui le précède.
? −→ présence éventuelle du caractère qui le précède. /clef?/
/t?riche/ /Ahh*/ /Ah+/
Les expressions régulières
Outils de description
Autres outils :
{ } −→ permettent de quantifier un nombre d’occurrences. Elles s’utilisent sous la forme {x,y}, avec x ≤ y et x, y ∈ N.
.−→ correspond à n’importe quel caractère.
[ ] −→ permettent de donner des classes d’équivalences de motifs. Le caractère ^permet de faire la négation d’une classe.
() −→ permettent de grouper des lettres ou des motifs. Après avoir matché la chaîne, les expressions correspondant aux motifs entre parenthèses sont stockées dans les variables $1,$2,. . .
| −→ définit une conditonnelle.
^−→ permet d’imposer la position du motif en début de chaîne. \ −→ permet de définir des caractères spéciaux et de quoter les méta caractères.
Les expressions régulières
Outils de description
/meuh{3}/ /meuh{3,5}/ /.*e/ /[pcfg]endre/ /toto.[^ch]/ /(meuh){3}/ if (m/Time:(..):(..):(..)/){ $heure = $1; $minute = $2; $seconde = $3; }Les expressions régulières
Outils de description
/(Pierre|Marie) Currie/ /^chatie/ $programme =~ m/(\/\*.*\*\/)/; print $1;Les expressions régulières
Caractères spéciaux
Caractère Equivalent Signification
\n Saut de ligne \r Retour chariot \t Tabulation \f Saut de page \e Echappement \d [0-9] Un chiffre \D [^0-9] Un caractère non-numérique
\w [0-9a-z] Un caractère alphanumérique dans un mot
\s [ \t\n\r\f] Un espace quelconque
Les expressions régulières
Spécifier le lieu
Des caractères spéciaux permettent de spécifier au moteur des lieux précis pour la correspondance de caractères.
Caractère Signification
\b Délimiteur de mot
\B Non délimiteur de mot
\A ou ^ Recherche en début de chaîne
\Z ou $ Recherche en fin de chaîne
/\bFred\b/ /Fred$/
Les expressions régulières
Options de recherche
Option Comportement
? après un quantifieur Cherche le plus petit motif
g Recherche globale, toutes les occurrences
i Ne tient pas compte de la casse
o Compile le motif une seule fois
m Traite la chaîne comme des lignes multiples
s Traite la chaîne comme une seule ligne
On peut également spécifier un symbole de remplacement du "/" $a = "/usr/local/share/emacs/site-lisp/";
$partition =~ m#/.*?/([^/]+)/.*/$#; print $1;
Les expressions régulières
La fonction grep
grep expr,liste
La fonction grep évalue, pour chaque élément de la liste, l’expression expr. Dans un contexte liste, elle retourne la liste des éléments pour lesquels l’expression a retourné VRAI.
Dans un contexte scalaire, elle retourne le nombre d’éléments pour lesquels l’expression a retrouné VRAI.
@users = grep /tcsh,@passwd; foreach (@users){
print $_."\n" if /home/; }
foreach (grep /home, grep /tcsh,@passwd){ print $_."\n";
Les expressions régulières
La fonction split
split /motif/,expr,lim
La fonction split effectue une recherche de motif dans expr et éclate expr dans un tableau qu’elle retourne. Par exemple :
@champs = split /:/,$ligne; print "$login = $champs[0]\n";
Si lim est spécifié, l’éclatement produira un tableau avec au plus lim éléments.
Les expressions régulières
Exercices
Ecrivez une fonction vérifiant qu’une chaîne saisie correspond bien à une immatriculation de véhicule en France. Il s’agit donc d’une immatriculation de la forme suivante : 2 lettres majuscules, 1 tiret, 3 chiffres, 1 tiret, 2 lettres majuscules (exemple : AA-000-AA).
Ecrivez une fonction vérifiant qu’une chaîne saisie correspond bien à une opération arithmétique entre entiers correcte non parenthésée, à savoir un nombre entier suivi d’un opérateur (+,-,*,/), suivi d’un autre nombre entier (n fois).
Ecrivez une fonction qui récupère une chaîne saisie par l’utilisateur et calcule le nombre de mots ainsi que le nombre de caractères contenus dans celle-ci.
Travailler avec des entrées/sorties
Travailler avec des entrées/sorties
Entrée/Sortie standard
Les entrées sorties standard sont, classiquement, le clavier et l’écran : clavier : STDIN
écran : STDOUT
Pour lire dans un flux de données, on utilise l’opérateur angle : <nom_du_flux>.
$name = <STDIN>; @notes = <STDIN>;
while ($a = <STDIN>) {print $a;}
L’opérateur est associé par défaut à STDIN et il met par défaut le résultat de sa lecture dans la variable $_.
Travailler avec des entrées/sorties
L’écriture
Standard
L’écriture sur les sorties (standard et erreur) se fait via la fonction print. Par défaut, elle écrit sur la sortie standard le contenu de la variable courante $_.
print STDOUT $_; = print $_; = print;
Elle écrit le second paramètre (chaîne) sur le premier (handle). Erreur
Pour envoyer un message d’erreur, on utilise généralement STDERR. La fonction warn affiche directement sur l’erreur standard.
if(err){ print STDERR "Il y a eu un problème\n"; } if(err){ warn "Il y a eu un problème\n"; }
Travailler avec des entrées/sorties
Les fichiers
Même procédure qu’en C :
1 Ouvrir le fichier et récupérer le Handle du fichier. 2 Manipuler le Handle.
3 Fermer le Handle.
open(hand,N); close(hand);
où hand est le nom du Handle et N un paramètre qui permet de décrire le nom du fichier et le mode d’ouverture.
Symbole Mode d’ouverture
> Ecriture
< Lecture
>> Ajout
+ > Lecture et écriture
Travailler avec des entrées/sorties
Les fichiers
open(LOG, ">>log") or die "Erreur",$! ; open(DATAS, "<$Donnees")or die "Erreur",$!;
open(SORTED,"sort -u $Donnees|") or die "Erreur",$! ; open(TOBESORT,"|sort -u") or die "Erreur",\$!;
die LISTE affiche la concaténation de la liste LISTE sur STDERR et sort du programme. $! contient la dernière erreur d’appel système.
Une fois le Handle du fichier ouvert, on l’utilise de la même manière que STDIN ou STDOUT.
Travailler avec des entrées/sorties
Exemple
$fileIn = shift; $fileOut = shift; $motif = shift;
## ouverture du fichier entree
open(INFILE, "<$fileIn") or die "Problème \"$fileIn\"", $!; ## ouverture du fichier sortie
open(OUTFILE, ">$fileOut") or die "Problème \"$fileIn\"", $!; while (<INFILE>){
## option o pour ne pas recompiler le motif print OUTFILE $_ if (/$motif/o);
}
close INFILE; close OUTFILE;
Travailler avec des entrées/sorties
Tests sur les fichiers
Syntaxe Test réalisé
-r/-w/-x Accessibilité en lecture/écriture/exécution -o Propriété -e Existence -z Taille 0 -s Retourne la taille -f Fichier simple -d Répertoire -l Lien symbolique -p Pipe -S Socket -B Fichier binaire -T Fichier texte
Travailler avec des entrées/sorties
Les répertoires
Changer de répertoire
Avec chdir : renvoie VRAI (1) ou FAUX ("").
chdir("/etc") or die "Impossible d’aller dans /etc ($!)"; Récupérer plusieurs noms de fichiers
Dans le répertoire courant, avec l’opérateur de globalisation glob expr (ou <expr>).
$where = "/etc/";
chdir($where) or die "impossible d’aller dans $where ($!)"; @lesfic = <host*>;
foreach $fic (@lesfic){ print $fic, "\n";
Travailler avec des entrées/sorties
Les répertoires
On peut ouvrir un répertoire (en lecture uniquement) avec opendir. On le ferme avec closedir.
opendir handle,expr; Plusieurs fonctions :
readdir HANDLEREP lit un nom de fichier.
rewindidr HANDLEREP repositionne au début du répertoire (pour reprendre l’énumération du début).
telldir HANDLEREP retourne la position courante.
Travailler avec des entrées/sorties
Opérations sur les fichiers
chmod LISTE change les permissions des fichiers contenus dans LISTE.
chown LISTE change propriétaire et groupe de chaque fichier de LISTE.
rename ANCIENNOM,NOUVEAUNOM change le nom d’un fichier. Renvoie 1 ou 0. Si NOUVEAUNOM existe déjà, il est détruit. symlink FEXIST,LIEN crée un lien symbolique de LIEN à FEXIST. rmdir HANDLEFIC détruit le fichier dont le Handle est HANDLEFIC. Retourne 1 ou 0 et s’applique par défaut à $_.
unlink LISTE détruit les fichiers spécifiés dans LISTE (ou le fichier $_) si pas d’argument liste. Renvoie le nombre de fichiers détruits. seek HANDLE,POS : même principe que seekdir sur les dossiers. tell existe aussi (sur le modèle de telldir ).
Travailler avec des entrées/sorties
Exercices
Ecrivez une fonction qui prend un nom de fichier en paramètre. Ce fichier contient des entiers (un par ligne). Votre fonction doit renvoyer le plus grand de ces nombres.
Un fichier contient une liste d’étudiants avec leurs notes respectives à un examen. Chaque ligne est de la forme nom de l’étudiant,note. Créez une fonction prenant le nom du fichier en paramètre et remplissant une table de hachage où le nom de l’étudiant correspond à la clé, tandis que la note correspond à la valeur. Vous afficherez ensuite la meilleure note, la moins bonne et la moyenne de classe.
Créez une fonction prenant en paramètre un nom de dossier et une date (sous la forme jj/mm/aaaa). Vous vérifierez que la date est au bon format). Cette fonction doit afficher la liste des fichiers ayant été modifiés après la date indiquée.
Divers
Divers
Les processus
Lancer des processus depuis un script Perl :
system LISTE exécute un programme existant sur le système en parallèle et attend qu’il se termine. Retourne 0 si l’exécution s’est bien passée.
exec LISTE exécute le programme contenu dans LISTE en le lançant à sa place. Ne rend la main qu’en cas de problème.
‘ ‘ fait la même chose que system, à la différence que la sortie standard de la commande est retourné sous forme de liste. exec ’/bin/echo’,@ARGV;
die "Impossible d’exécuter csh : $!\n"; $motif = shift;
@reps = ‘find . -type d -print‘; foreach(@reps){
Divers
Les fonctions
Les fonctions (ou sous-programmes) disposent de leur espace de nom propre. Elles se déclarent ainsi :
sub NOM;
Elles se définissent ainsi : sub NOM BLOC
Pour appeler une fonction : Nom (LISTE);
&Nom LISTE;
Le sous-programme récupère ses paramètres dans le tableau @_. Il
Divers
Les fonctions
#!/usr/local/bin/perl -w
## Perl
-*-sub minmax{
## récupère la premiere valeur de @_ $min =$max = shift;
## pour chaque valeur dans @_
## on met a jour le min et le max si nécessaire while ($courant = shift){
$max = $courant if ($courant > $max) ; $min = $courant if ($courant < $min); }
($min, $max); }
Divers
Les fonctions
## on met dans @_ le contenu de STDIN
## a raison d’une ligne par case du tableau @_ = <STDIN>;
## appel a minmax -> on recupere dans $t le min et $a le max ($t, $a) = &minmax;
chomp ($t, $a);
Divers
Les variables locales
Deux méthodes pour créer des variables locales :
my expr permet de déclarer une variable privée dans le
bloc/sous-programme/fichier qui l’encadre. my($v1,$v2,$v3) = @_ est possible.
local expr utilise la même syntaxe que my. La différence est que local fait une sauvegarde de la valeur de la variable pour la restituer à la fin de la portée
La différence entre les deux est don essetniellement une différence de portée. L’intérêt de local est donc principalement dans les fonctions récursives et celles qui ont des effets de bord sur les variables globales.
Divers
Les variables locales
if(scalar @ARGV){
local @ARGV = @ARGV; print "parametre "; while($_ = shift){ print " $_"; } print "\n"; }
print "\n", ’affichage de @ARGV:’, "@ARGV\n"; ###Exécution###
script a b c d e --->
Divers
Les variables locales
if(scalar @ARGV){ my @ARGV = @ARGV; print "parametre "; while($_ = shift){ print " $_"; } print "\n"; }
print "\n", ’affichage de @ARGV 2 :’, "@ARGV\n"; ###Exécution###
script a b c d e --->
Divers
Exercices
Créez une fonction qui calcule la factorielle d’un nombre passé en paramètre, de façon récursive.
Ecrivez un programme qui parcourt l’aborescence depuis le répertoire courant et qui supprime les fichiers dont l’extension est entrée en paramètre.
Divers