Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1122 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  fichiers et fonctions

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

fichiers et fonctions

n°2245255
laisso
Posté le 07-12-2014 à 22:52:23  profilanswer
 

Bonjour, j'ai une problématique face à un sujet : en effet, mon prof m'a envoyé un parcours d'une arborescence. Je ne vois pas la différence avec l'énonce. Le prof nous demande de nous servir de cette arborescence pour faire le code répondant à l'exercice.
 
Chercher dans un dossier donné, et ses sous-dossiers, tous les fichiers qui contiennent des lignes commençant par un mot donné et écrire dans un fichier rapport la liste des fichiers répondant au critère.
Le parcours du dossier devra se faire dans une fonction (utilisation de « sub ») distincte du reste du programme.
Le rapport sera présenté de la façon suivante :
 
Date : Thu Nov  7 10:01:41 2013
Dossier : /chemin/dossier
 
fichier1
ligne du fichier1 commençant par le mot cherché
ligne suivante du fichier1 commençant par le mot cherché
...
dernière ligne du fichier1 commençant par le mot cherché
 
fichier2
ligne du fichier2 commençant par le mot cherché
ligne suivante du fichier2 commençant par le mot cherché
 

Code :
  1. sub AnalyseDossier {
  2. # La fonction analyseDossier attend un seul paramètre qui est le nom du dossier qu'on veut analyser
  3. my $D= shift @_; # On recupere le nom du dossier...
  4. # ouverture du dossier $D et creation du descripteur REP
  5. opendir (REP,$D) or die ("Impossible d'ouvrir le repertoire ",$D);
  6. # On recupere les fichiers du descripteur REP dans @listFile
  7. # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  8. my @listFile = readdir (REP);
  9. # on ferme le descripteur
  10. close (REP);
  11. # Parcours des éléments du dossier $D, ils peuvent $etre des fichiers ou des dossiers
  12. foreach (@listFile) {
  13.  # Création du nom complet :
  14.  my $nomComplet = $D."/".$_;
  15.  # S'il s'agit d'un fichier on le traite via la fonction de traitement
  16.  if (-f $nomComplet) {
  17.   traitement($nomComplet);
  18.  }
  19.  # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
  20.  elsif (-d $nomComplet and $_ ne "." and $_ ne ".." ) {
  21.   # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
  22.   AnalyseDossier ($nomComplet);
  23.  }
  24. } # fin de foreach (@listFile)
  25. } # fin de fonction analyseDossier
  26. sub traitement {
  27. # Ici on se contente d'afficher le nom du fichier et sa taille
  28. # On récupère le paramètre passé à la fonction traitement :
  29. my $nomComplet = shift @_; # c'est le nom complet du fichier
  30. my $taille = -s  ($nomComplet);
  31. print "\n$nomComplet : $taille";
  32. } # fin de fonction traitement
  33. ###### PROGRAMME PRINCIPAL ######
  34. print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner";
  35. print "\nIl va afficher tous les fichiers et les sous-dossiers";
  36. print "\nPour chaque fichier, on affichera le nom et la taille";
  37. # saisie
  38. print "\n\nQuel dossier ? Entrez le nom complet\n";
  39. $D = <STDIN>;
  40. chomp $D;
  41. # traitement
  42. if (-d $D) {
  43. AnalyseDossier ($D);
  44. }
  45. else {
  46. die ("Impossible d'ouvrir le repertoire ",$D);
  47. }
  48. print "\n\nAu revoir !\n\n";

mood
Publicité
Posté le 07-12-2014 à 22:52:23  profilanswer
 

n°2245312
gilou
Modérateur
Modzilla
Posté le 08-12-2014 à 11:49:07  profilanswer
 

C'est le sub traitement, qui actuellement n'imprime que le nom complet, que tu dois modifier afin d'obtenir la sortie désirée par ton prof.
Un indice: jettes un œil à la fonction grep de perl, sachant que si tu as ouvert un fichier avec open(my $fh, '<', "mon_fichier" ), tu peu faire un grep /la bonne regexp/ <$fh> pour filtrer les lignes du fichier (et sachant aussi que la solution bateau attendue par ton prof sera une lecture ligne a ligne, un test (avec la même bonne regexp) pour chaque ligne et l'impression à la console si la ligne passe le test).
 
A+,

Message cité 1 fois
Message édité par gilou le 08-12-2014 à 12:20:58

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2245762
laisso
Posté le 11-12-2014 à 16:03:27  profilanswer
 

gilou a écrit :

C'est le sub traitement, qui actuellement n'imprime que le nom complet, que tu dois modifier afin d'obtenir la sortie désirée par ton prof.
Un indice: jettes un œil à la fonction grep de perl, sachant que si tu as ouvert un fichier avec open(my $fh, '<', "mon_fichier" ), tu peu faire un grep /la bonne regexp/ <$fh> pour filtrer les lignes du fichier (et sachant aussi que la solution bateau attendue par ton prof sera une lecture ligne a ligne, un test (avec la même bonne regexp) pour chaque ligne et l'impression à la console si la ligne passe le test).
 
A+,


 
Bonjour, J'ai réussi à obtenir ce code. Qu'en pensez vous?
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use utf8;
  5. ######*PROGRAMME PRINCIPAL ######
  6. print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner";
  7. print "\nIl va afficher tous les fichiers et les sous-dossiers";
  8. print "\nPour chaque fichier, on affichera le nom et la taille";
  9. print "\nPour chaque fichier on recherche la correspondance d'un mot en début de ligne";
  10. print "\nOn écrit le résultat dans le fichier Rapport.txt\n\n";
  11. # saisie
  12. print "\n\nQuel dossier ? Entrez le nom complet\n";
  13. my $D = <STDIN>;
  14. chomp $D;
  15. print "\n\nEntrez le mot recherché :\n";
  16. my $M = <STDIN>;
  17. chomp $M;
  18. print "$D - $M\n";
  19. open my $FH_OUT, '>:utf8', './Rapport.txt' or die "ouverture impossible de Rapport.txt $!";     # ouverture du fichier rapport
  20. print $FH_OUT date();
  21. print $FH_OUT "\nDossier : $D - Mot recherché : $M\n\n";;
  22. # traitement
  23. if (-d $D) {
  24. AnalyseDossier ($D);
  25. }
  26. else {
  27. die ("Impossible d'ouvrir le repertoire ",$D);
  28. }
  29. close $FH_OUT;
  30. print "\n\nAu revoir !\n\n";
  31. sub AnalyseDossier {
  32. # La fonction analyseDossier attend un seul paramètre qui est le nom du dossier qu'on veut analyser
  33. my $D= shift @_; # On recupere le nom du dossier...
  34. # ouverture du dossier $D et creation du descripteur REP
  35. opendir (REP,$D) or die ("Impossible d'ouvrir le repertoire ",$D);
  36. # On recupere les fichiers du descripteur REP dans @listFile
  37. # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  38. my @listFile = readdir (REP);
  39. # on ferme le descripteur
  40. close (REP);
  41. # Parcours des éléments du dossier $D, ils peuvent $etre des fichiers ou des dossiers
  42. foreach (@listFile) {
  43.  # Création du nom complet :
  44.  my $nomComplet = $D."/".$_;
  45.  # S'il s'agit d'un fichier on le traite via la fonction de traitement
  46.  if (-f $nomComplet) {
  47.   traitement($nomComplet);
  48.  }
  49.  # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
  50.  elsif (-d $nomComplet and $_ ne "." and $_ ne ".." ) {
  51.   # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
  52.   AnalyseDossier ($nomComplet);
  53.  }
  54. } # fin de foreach (@listFile)
  55. } # fin de fonction analyseDossier
  56. sub traitement {
  57. # Ici on se contente d'afficher le nom du fichier et sa taille
  58. # On récupère le paramètre passé à la fonction traitement :
  59. my $nomComplet = shift @_; # c'est le nom*complet du fichier
  60. my $taille = -s  ($nomComplet);
  61. print $FH_OUT "\n\n$nomComplet : $taille\n";
  62. open my $FH_IN, "<:utf8", $nomComplet or die "ouverture impossible de $nomComplet $!";     # ouverture du fichier courant en lecture
  63. while (my $ligne = <$FH_IN> ) {                      # lecture du fichier courant
  64.  if ( $ligne =~ /^$M/ ) {                          # recherche du motif en début de ligne
  65.   print $FH_OUT "$ligne";
  66.  }
  67. }
  68. close $FH_IN;                                       # la fermeture du handle
  69. } # fin de fonction traitement
  70. ###############
  71. # Date et Heure
  72. sub date {
  73.   my $time = shift || time;    #$time par defaut vaut le time actuel
  74.   my ( $seconde, $minute, $heure, $jour, $mois, $annee, $jour_semaine, $jour_annee, $heure_hiver_ou_ete )
  75.     = localtime($time);
  76.   $mois  += 1;
  77.   $annee += 1900;
  78.   # On rajoute 0 si le chiffre est compris entre 1 et 9
  79.   foreach ( $seconde, $minute, $heure, $jour, $mois, $annee ) { s/^(\d)$/0$1/; }
  80.   return "Le $jour/$mois/$annee à $heure:$minute:$seconde";
  81. }


 
 

n°2245796
gilou
Modérateur
Modzilla
Posté le 11-12-2014 à 19:12:03  profilanswer
 

Je pense que déjà, ça serait sympa si vous formatiez et aériez le code.
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use utf8;
  5.  
  6. ######*PROGRAMME PRINCIPAL ######
  7. print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner";
  8. print "\nIl va afficher tous les fichiers et les sous-dossiers";
  9. print "\nPour chaque fichier, on affichera le nom et la taille";
  10. print "\nPour chaque fichier on recherche la correspondance d'un mot en début de ligne";
  11. print "\nOn écrit le résultat dans le fichier Rapport.txt\n\n";
  12. # saisie
  13. print "\n\nQuel dossier ? Entrez le nom complet\n";
  14. my $D = <STDIN>;
  15. chomp $D;
  16. print "\n\nEntrez le mot recherché :\n";
  17. my $M = <STDIN>;
  18. chomp $M;
  19. print "$D - $M\n";
  20. open my $FH_OUT, '>:utf8', './Rapport.txt' or die "ouverture impossible de Rapport.txt $!"; # ouverture du fichier rapport
  21. print $FH_OUT date();
  22. print $FH_OUT "\nDossier : $D - Mot recherché : $M\n\n";;
  23. # traitement
  24. if (-d $D) {
  25.  AnalyseDossier ($D);
  26. } else {
  27.  die ("Impossible d'ouvrir le repertoire ",$D);
  28. }
  29. close $FH_OUT;
  30. print "\n\nAu revoir !\n\n";
  31.  
  32.  
  33. sub AnalyseDossier {
  34.  # La fonction analyseDossier attend un seul paramètre qui est le nom du dossier qu'on veut analyser
  35.  my $D= shift @_;        # On recupere le nom du dossier...
  36.  # ouverture du dossier $D et creation du descripteur REP
  37.  opendir (REP,$D) or die ("Impossible d'ouvrir le repertoire ",$D);
  38.  # On recupere les fichiers du descripteur REP dans @listFile
  39.  # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  40.  my @listFile = readdir (REP);
  41.  # on ferme le descripteur
  42.  close (REP);
  43.  # Parcours des éléments du dossier $D, ils peuvent $etre des fichiers ou des dossiers
  44.  foreach (@listFile) {
  45.    # Création du nom complet :
  46.    my $nomComplet = $D."/".$_;
  47.    # S'il s'agit d'un fichier on le traite via la fonction de traitement
  48.    if (-f $nomComplet) {
  49.      traitement($nomComplet);
  50.    }
  51.    # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
  52.    elsif (-d $nomComplet and $_ ne "." and $_ ne ".." ) {
  53.      # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
  54.      AnalyseDossier ($nomComplet);
  55.    }
  56.  }                # fin de foreach (@listFile)
  57. }                # fin de fonction analyseDossier
  58.  
  59.  
  60. sub traitement {
  61.  # Ici on se contente d'afficher le nom du fichier et sa taille
  62.  # On récupère le paramètre passé à la fonction traitement :
  63.  my $nomComplet = shift @_;    # c'est le nom*complet du fichier
  64.  my $taille = -s  ($nomComplet);
  65.  print $FH_OUT "\n\n$nomComplet : $taille\n";
  66.  open my $FH_IN, "<:utf8", $nomComplet or die "ouverture impossible de $nomComplet $!"; #
  67.  
  68. ouverture du fichier courant en lecture
  69.  while (my $ligne = <$FH_IN> ) { # lecture du fichier courant
  70.    if ( $ligne =~ /^$M/ ) {    # recherche du motif en début de ligne
  71.      print $FH_OUT "$ligne";
  72.    }
  73.  }
  74.  close $FH_IN;            # la fermeture du handle
  75. }
  76.  
  77.                 # fin de fonction traitement
  78. ###############
  79. # Date et Heure
  80. sub date {
  81.  my $time = shift || time;    #$time par defaut vaut le time actuel
  82.  my ( $seconde, $minute, $heure, $jour, $mois, $annee, $jour_semaine, $jour_annee,
  83.  
  84. $heure_hiver_ou_ete )
  85.    = localtime($time);
  86.  $mois  += 1;
  87.  $annee += 1900;
  88.  # On rajoute 0 si le chiffre est compris entre 1 et 9
  89.  foreach ( $seconde, $minute, $heure, $jour, $mois, $annee ) {
  90.    s/^(\d)$/0$1/;
  91.  }
  92.  return "Le $jour/$mois/$annee à $heure:$minute:$seconde";
  93. }


 
A+,


Message édité par gilou le 11-12-2014 à 19:13:37

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2245900
gilou
Modérateur
Modzilla
Posté le 12-12-2014 à 15:23:26  profilanswer
 

Je n'ai pas testé l'ensemble, mais c'est l'idée.
 
Quelques remarques:
- éviter les  
 
print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner";
print "\nIl va afficher tous les fichiers et les sous-dossiers";
print "\nPour chaque fichier, on affichera le nom et la taille";
print "\nPour chaque fichier on recherche la correspondance d'un mot en début de ligne";
print "\nOn écrit le résultat dans le fichier Rapport.txt\n\n";
 
et utiliser plutôt ce style:
 
print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner\n";
print "Il va afficher tous les fichiers et les sous-dossiers\n";
print "Pour chaque fichier, on affichera le nom et la taille\n";
print "Pour chaque fichier on recherche la correspondance d'un mot en début de ligne\n";
print "On écrit le résultat dans le fichier Rapport.txt\n\n";
 
Ce n'est peut être pas important en Perl, mais il y a pas mal de langages ou le fait d'avoir un \n en fin de texte a afficher est significatif (ie déclenche l'affichage).
 
- my $D= shift @_;   a remplacer par my $D= shift;  
C'est la même chose, mais c'est la pratique courante, de ne pas écrire les variables implicites quand c'est évident.
 
idem ici:
while (my $ligne = <$FH_IN> ) { # lecture du fichier courant
    if ( $ligne =~ /^$M/ ) { # recherche du motif en début de ligne
      print $FH_OUT "$ligne";
    }
 
la pratique pour ce genre de boucle simple serait plutôt d'écrire
while (<$FH_IN> ) { # lecture du fichier courant
    if ( /^$M/ ) { # recherche du motif en début de ligne
      print $FH_OUT $_;
    }
avec la variable implicite $_
 
- d'autre part, réserver les majuscules aux variables globales: $FH_IN -> $fh_in
 
 
 
opendir (REP,$D) or die ("Impossible d'ouvrir le repertoire ",$D);
  # On recupere les fichiers du descripteur REP dans @listFile
  # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  my @listFile = readdir (REP);
  # on ferme le descripteur
  close (REP);
 
Primo, l'erreur: ça doit être closedir et non pas close.
D'autre part, aucune raison de ne pas utiliser des variables locales:
opendir (my $rep, $D) or die ("Impossible d'ouvrir le repertoire ",$D);
  # On recupere les fichiers du descripteur $rep dans @listFile
  # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  my @listFile = readdir ($rep);
  # on ferme le descripteur
  closedir ($rep);
 
- plutôt que faire un test complexe  
elsif (-d $nomComplet and $_ ne "." and $_ ne ".." )
autant éliminer . et .. a la source:
my @listFile = grep !/^\.{1,2}$/o, readdir ($rep);
 
- enfin
foreach (@listFile) {
    # Création du nom complet :
    my $nomComplet = $D."/".$_;
    # S'il s'agit d'un fichier on le traite via la fonction de traitement
    if (-f $nomComplet) {
      traitement($nomComplet);
    }
    # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
    elsif (-d $nomComplet) {
      # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
      AnalyseDossier ($nomComplet);
    }
  }
 
un elseif pas suivi de else, j'aime pas.
Ce serait plus simple ainsi:
foreach (@listFile) {
    # Création du nom complet :
    my $nomComplet = $D."/".$_;
    # S'il s'agit d'un fichier on le traite via la fonction de traitement
    if (-f $_) {
      traitement($nomComplet);
      next;
    }
    # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
    if (-d $_) {
      AnalyseDossier ($nomComplet);
      next;
    }
  }
 et c'est probablement plus optimisé en faisant if (-d _) (après un premier test de fichier -f, -d, ... la variable _ contient les infos relatives au fichier, pour être réutilisée avec d'autres tests de fichier, sinon, chaque test fait un appel système fstat ou stat, ce qui est plus long)
 
 
- pensez aussi à utiliser  
use autodie;
 
ce qui permet de remplacer
open my $FH_OUT, '>:utf8', './Rapport.txt' or die "ouverture impossible de Rapport.txt $!"; # ouverture du fichier rapport
par
open my $FH_OUT, '>:utf8', './Rapport.txt';
(bon, vérifier quand même en quelle langue sera le message d'erreur automatique dans ce dernier cas)
 
A+,


Message édité par gilou le 12-12-2014 à 15:23:49

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2245948
laisso
Posté le 12-12-2014 à 23:49:16  profilanswer
 

[quotemsg=2245900,5,19304]Je n'ai pas testé l'ensemble, mais c'est l'idée.
 
Quelques remarques:
- éviter les  
 
print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner";
print "\nIl va afficher tous les fichiers et les sous-dossiers";
print "\nPour chaque fichier, on affichera le nom et la taille";
print "\nPour chaque fichier on recherche la correspondance d'un mot en début de ligne";
print "\nOn écrit le résultat dans le fichier Rapport.txt\n\n";
 
et utiliser plutôt ce style:
 
print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner\n";
print "Il va afficher tous les fichiers et les sous-dossiers\n";
print "Pour chaque fichier, on affichera le nom et la taille\n";
print "Pour chaque fichier on recherche la correspondance d'un mot en début de ligne\n";
print "On écrit le résultat dans le fichier Rapport.txt\n\n";
 
Ce n'est peut être pas important en Perl, mais il y a pas mal de langages ou le fait d'avoir un \n en fin de texte a afficher est significatif (ie déclenche l'affichage).
 
- my $D= shift @_;   a remplacer par my $D= shift;  
C'est la même chose, mais c'est la pratique courante, de ne pas écrire les variables implicites quand c'est évident.
 
idem ici:
while (my $ligne = <$FH_IN> ) { # lecture du fichier courant
    if ( $ligne =~ /^$M/ ) { # recherche du motif en début de ligne
      print $FH_OUT "$ligne";
    }
 
la pratique pour ce genre de boucle simple serait plutôt d'écrire
while (<$FH_IN> ) { # lecture du fichier courant
    if ( /^$M/ ) { # recherche du motif en début de ligne
      print $FH_OUT $_;
    }
avec la variable implicite $_
 
- d'autre part, réserver les majuscules aux variables globales: $FH_IN -> $fh_in
 
 
 
opendir (REP,$D) or die ("Impossible d'ouvrir le repertoire ",$D);
  # On recupere les fichiers du descripteur REP dans @listFile
  # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  my @listFile = readdir (REP);
  # on ferme le descripteur
  close (REP);
 
Primo, l'erreur: ça doit être closedir et non pas close.
D'autre part, aucune raison de ne pas utiliser des variables locales:
opendir (my $rep, $D) or die ("Impossible d'ouvrir le repertoire ",$D);
  # On recupere les fichiers du descripteur $rep dans @listFile
  # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  my @listFile = readdir ($rep);
  # on ferme le descripteur
  closedir ($rep);
 
- plutôt que faire un test complexe  
elsif (-d $nomComplet and $_ ne "." and $_ ne ".." )
autant éliminer . et .. a la source:
my @listFile = grep !/^\.{1,2}$/o, readdir ($rep);
 
- enfin
foreach (@listFile) {
    # Création du nom complet :
    my $nomComplet = $D."/".$_;
    # S'il s'agit d'un fichier on le traite via la fonction de traitement
    if (-f $nomComplet) {
      traitement($nomComplet);
    }
    # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
    elsif (-d $nomComplet) {
      # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
      AnalyseDossier ($nomComplet);
    }
  }
 
un elseif pas suivi de else, j'aime pas.
Ce serait plus simple ainsi:
foreach (@listFile) {
    # Création du nom complet :
    my $nomComplet = $D."/".$_;
    # S'il s'agit d'un fichier on le traite via la fonction de traitement
    if (-f $_) {
      traitement($nomComplet);
      next;
    }
    # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
    if (-d $_) {
      AnalyseDossier ($nomComplet);
      next;
    }
  }
 et c'est probablement plus optimisé en faisant if (-d _) (après un premier test de fichier -f, -d, ... la variable _ contient les infos relatives au fichier, pour être réutilisée avec d'autres tests de fichier, sinon, chaque test fait un appel système fstat ou stat, ce qui est plus long)
 
 
- pensez aussi à utiliser  
use autodie;
 
ce qui permet de remplacer
open my $FH_OUT, '>:utf8', './Rapport.txt' or die "ouverture impossible de Rapport.txt $!"; # ouverture du fichier rapport
par
open my $FH_OUT, '>:utf8', './Rapport.txt';
(bon, vérifier quand même en quelle langue sera le message d'erreur automatique dans ce dernier cas)
 
Bonjour,
 
Voici la modification, Seulement voila le fichier . txt ne se génére pas prq?
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use utf8;
  5. use autodie;
  6. ######*PROGRAMME PRINCIPAL ######
  7. print "\nCe programme parcourt toute l'arborescence d'un dossier que vous allez donner\n";
  8. print "Il va afficher tous les fichiers et les sous-dossiers\n";
  9. print "Pour chaque fichier, on affichera le nom et la taille\n";
  10. print "Pour chaque fichier on recherche la correspondance d'un mot en début de ligne\n";
  11. print "On écrit le résultat dans le fichier Rapport.txt\n\n";
  12. # saisie
  13. print "\n\nQuel dossier ? Entrez le nom complet\n";
  14. my $D = <STDIN>;
  15. chomp $D;
  16. print "\n\nEntrez le mot recherché :\n";
  17. my $M = <STDIN>;
  18. chomp $M;
  19. print "$D - $M\n";
  20. open my $FH_OUT, '>:utf8', './Rapport.txt';  # ouverture du fichier rapport
  21. print $FH_OUT date();
  22. print $FH_OUT "\nDossier : $D - Mot recherché : $M\n\n";;
  23. # traitement
  24. if (-d $D) {
  25. AnalyseDossier ($D);
  26. }
  27. else {
  28. die ("Impossible d'ouvrir le repertoire ",$D);
  29. }
  30. close $FH_OUT;
  31. print "\n\nAu revoir !\n\n";
  32. sub AnalyseDossier {
  33. # La fonction analyseDossier attend un seul paramètre qui est le nom du dossier qu'on veut analyser
  34. my $D= shift; # On recupere le nom du dossier...
  35. # ouverture du dossier $D et creation du descripteur REP
  36. opendir (my $rep, $D) or die ("Impossible d'ouvrir le repertoire ",$D);
  37. # On recupere les fichiers du descripteur REP dans @listFile
  38. # Notez bien que @listFile peut contenir à la fois des dossiers et des fichiers
  39. my @listFile = grep !/^\.{1,2}$/o, readdir ($rep);
  40. # on ferme le descripteur
  41. closedir ($rep);
  42. # Parcours des éléments du dossier $D, ils peuvent $etre des fichiers ou des dossiers
  43. foreach (@listFile) {
  44.  # Création du nom complet :
  45.  my $nomComplet = $D."/".$_;
  46.  # S'il s'agit d'un fichier on le traite via la fonction de traitement
  47.  if (-f $_) {
  48.   traitement($nomComplet);
  49.   next;
  50.  }
  51.  # sinon s'il s'agit d'un dossier autre que les dossiers . et ..
  52.  if (-d $_)  {
  53.   # ... on lance un nouvel appel récursif à notre fonction, sur ce dossier là :
  54.   AnalyseDossier ($nomComplet);
  55.   next;
  56.  }
  57. } # fin de foreach (@listFile)
  58. } # fin de fonction analyseDossier
  59. sub traitement {
  60. # Ici on se contente d'afficher le nom du fichier et sa taille
  61. # On récupère le paramètre passé à la fonction traitement :
  62. my $nomComplet = shift @_; # c'est le nom complet du fichier
  63. my $taille = -s  ($nomComplet);
  64. print $FH_OUT "\n\n$nomComplet : $taille\n";
  65. open my $fh_in, "<:utf8", $nomComplet or die "ouverture impossible de $nomComplet $!";  # ouverture du fichier courant en lecture
  66. while ( <$fh_in> ) {     # lecture du fichier courant
  67.  if ( /^$M/ ) {       # recherche du motif en début de ligne
  68.   print $FH_OUT $_;
  69.  }
  70. }
  71. close $fh_in;  # la fermeture du handle
  72. } # fin de fonction traitement
  73. ###############
  74. # Date et Heure
  75. sub date {
  76.   my $time = shift || time;    #$time par defaut vaut le time actuel
  77.   my ( $seconde, $minute, $heure, $jour, $mois, $annee, $jour_semaine, $jour_annee, $heure_hiver_ou_ete )
  78.     = localtime($time);
  79.   $mois  += 1;
  80.   $annee += 1900;
  81.   # On rajoute 0 si le chiffre est compris entre 1 et 9
  82.  
  83.   foreach ( $seconde, $minute, $heure, $jour, $mois, $annee ) { s/^(\d)$/0$1/; }
  84.   return "Le $jour/$mois/$annee à $heure:$minute:$seconde";
  85. }


Message édité par laisso le 13-12-2014 à 00:21:07
n°2245952
gilou
Modérateur
Modzilla
Posté le 13-12-2014 à 04:05:48  profilanswer
 

Oui, j'avais lu un peu trop vite le code, si tu remplaces les tests
if (-f $_) et if (-d $_)
par
if (-f $nomComplet) et if (-d $nomComplet)
ça marchera.
Habituellement, je fais un cd dans le répertoire pour utiliser directement la liste retournée par opendir
 
un petit conseil: remplaces le test if (-f $nomComplet) par if (-T $nomComplet) vu que seuls les fichiers texte t'intéressent.
Ou j'aurais gardé -f et testé pour -T avant ouverture du fichier si tu veux lister les fichier non texte
 
 
Notes que en Perl, un principe de base est d'utiliser les modules déjà existant.
J'aurais utilisé File::Find  (use File::Find; en tête) et remplacé une partie de ton code par
 

Code :
  1. # traitement
  2. if (-d $D) {
  3.  find(\&wanted, $D);
  4. }
  5. else {
  6.  die ("Impossible d'ouvrir le repertoire ",$D);
  7. }
  8. close $FH_OUT;
  9. print "\n\nAu revoir !\n\n";
  10.  
  11. sub wanted {
  12.  if (-f $_) {
  13.    my $taille = -s _;
  14.    print $FH_OUT "\n\n$File::Find::dir/$_ : $taille\n";
  15.    if (-T _) {
  16.        traitement($_);
  17.    }
  18.    return;
  19.  }
  20. }
  21.  
  22. sub traitement {
  23. open my $fh_in, "<:utf8", shift;  # ouverture du fichier courant en lecture
  24. while ( <$fh_in> ) {     # lecture du fichier courant
  25.  if ( /^$M/ ) {       # recherche du motif en début de ligne
  26.    print $FH_OUT $_;
  27.  }
  28. }
  29. close $fh_in;  # la fermeture du handle
  30. } # fin de fonction traitement


 
find(\&wanted, $D); va faire un parcours récursif de $D et ses sous répertoires, et pour chaque fichier ou répertoire, il va appeler la sub wanted (on peut la renommer si on veut) avec le nom du fichier/répertoire dans $_ et son répertoire dans $File::Find::dir, et de plus, ça vire les cas de '.' et '..' automatiquement
A+,


Message édité par gilou le 13-12-2014 à 12:45:45

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2245959
laisso
Posté le 13-12-2014 à 11:08:01  profilanswer
 

Merci c'est résolu.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  fichiers et fonctions

 

Sujets relatifs
Recuperer des fichiers txt d'un ftp sur access 2013fichier bat pour copie de fichiers anterieur a une date
Renommer fichiers avec le nom de leurs dossierFonctions avec requetes en base MySQL
Impression automatiser avec différents type de fichiersIntranet - Server "web" LAN ouverture fichiers partager
Tableaux - Fichiers - Fonctions - Procédures[Résolu]Ouverture de fichiers et fonctions
Fichiers et fonctionsiis et les fonctions asp sur les fichiers
Plus de sujets relatifs à : fichiers et fonctions


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR