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

  FORUM HardWare.fr
  Programmation
  Perl

  perl - lister les fichiers d'un rep

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

perl - lister les fichiers d'un rep

n°2088779
belette59
Posté le 11-07-2011 à 19:12:34  profilanswer
 

Hello !  
 
J'aurais besoin de l'équivalent de la commande suivante en perl :
 

Code :
  1. /usr/bin/find /home/belette//?/?/ -type f -name "*.log" -exec /usr/bin/stat -c "%s %n" {} \;


 
car le problème, c'est que c'est lent car il y a environ 1 000 000 de fichiers.
On m'a dit que parser les sous rep en perl était beaucoup plus rapide mais je n'en ai jamais fait :(
 
Est ce que vous auriez qqch sous la main ?.
 
Merci
 


---------------

mood
Publicité
Posté le 11-07-2011 à 19:12:34  profilanswer
 

n°2088809
gilou
Modérateur
Modzilla
Posté le 11-07-2011 à 21:56:27  profilanswer
 

Sur mon PC, ceci:

C:\Perl>find2perl /home/belette//?/?/ -type f -name "*.log" -exec /usr/bin/stat -c "%s %n" {} \;


génère ce script:
 

Code :
  1. #! C:\Perl\bin\perl.exe -w
  2.    eval 'exec C:\Perl\bin\perl.exe -S $0 ${1+"$@"}'
  3.        if 0; #$running_under_some_shell
  4.  
  5. use strict;
  6. use File::Find ();
  7.  
  8. # Set the variable $File::Find::dont_use_nlink if you're using AFS,
  9. # since AFS cheats.
  10.  
  11. # for the convenience of &wanted calls, including -eval statements:
  12. use vars qw/*name *dir *prune/;
  13. *name   = *File::Find::name;
  14. *dir    = *File::Find::dir;
  15. *prune  = *File::Find::prune;
  16.  
  17. sub wanted;
  18. sub doexec ($@);
  19.  
  20.  
  21. use Cwd ();
  22. my $cwd = Cwd::cwd();
  23.  
  24.  
  25. # Traverse desired filesystems
  26. File::Find::find({wanted => \&wanted}, '/home/belette//?/?/');
  27.  
  28.  
  29. sub wanted {
  30.    my ($dev,$ino,$mode,$nlink,$uid,$gid);
  31.  
  32.    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  33.    -f _ &&
  34.    /^.*\.log\z/s &&
  35.    doexec(0, '/usr/bin/stat','-c','%s %n','{}','\;');
  36. }
  37.  
  38.  
  39. sub doexec ($@) {
  40.    my $ok = shift;
  41.    my @command = @_; # copy so we don't try to s/// aliases to constants
  42.    for my $word (@command)
  43.        { $word =~ s#{}#$name#g }
  44.    if ($ok) {
  45.        my $old = select(STDOUT);
  46.        $| = 1;
  47.        print "@command";
  48.        select($old);
  49.        return 0 unless <STDIN> =~ /^y/;
  50.    }
  51.    chdir $cwd; #sigh
  52.    system @command;
  53.    chdir $File::Find::dir;
  54.    return !$?;
  55. }


A toi de voir ce que la commande génère dans ton environnement linux ou unix, puis à toi d'optimiser, comme je l'avais fait dans cet exemple ci: http://forum.hardware.fr/hfr/Progr [...] m#t1940849
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2088810
gilou
Modérateur
Modzilla
Posté le 11-07-2011 à 22:07:15  profilanswer
 

Pas sur que ton path initial avec des ? marche dans File::Find::find({wanted => \&wanted}, '/home/belette//?/?/'); d'ailleurs.
Il faudra peut être d'abord établir la liste des répertoires qui matchent ce pattern.
le // après belette, c'est volontaire (avec quel sens alors) ou bien c'est une faute de frappe pour un seul /  :??:  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2088813
belette59
Posté le 11-07-2011 à 22:17:04  profilanswer
 

Hello,  
merci pour vos infos.
 
Sinon, oui, le ?, c'est fait expres, car j'ai des sous repertoires A, B, C, D, E, F, G et H ( et la meme chose en sous-sous rep), ya du postfix qui tourne dessus.
 
sinon, oui, le //, c'est une faute de frappe :)


---------------

n°2088887
gilou
Modérateur
Modzilla
Posté le 12-07-2011 à 12:04:24  profilanswer
 

Bon, en regardant d'un peu plus près ce qu'il y a à simplifier, ceci devrait coller, si j'ai bien pigé ce que tu veux faire.

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use File::Find;
  6.  
  7. my $level = -1;
  8. sub wanted {
  9.  if (-d) {
  10.    $level++;
  11.    if (($level > 2) or (!/^.$/o)) {
  12.      $File::Find::prune = 1;
  13.    }
  14.    else {
  15.      $File::Find::prune = 0;
  16.    }
  17.    $level--;
  18.  }
  19.  if (-f) {
  20.    if (($level == 2) and (/\.log$/o)) {
  21.      my $fsize = (stat($_))[7];
  22.      print "$fsize octets $File::Find::name\n"; # a adapter a son format voulu
  23.    }
  24.  }
  25. }
  26.  
  27.  
  28. File::Find::find({wanted => \&wanted,
  29.           preprocess =>  sub {$level++; return @_},
  30.           postprocess => sub {$level--}}, '/home/belette');


(le but étant d'éviter de faire system @command; à de nombreuses reprises, comme dans le script généré par find2perl, ce qui ralentit l’exécution, quand il y a des commandes built-in perl qui peuvent le faire)
 
PS: Ma solution précédente supposait que tous tes fichiers étaient dans des sous répertoires à deux niveaux en dessous de /home/belette et pas plus bas.
Mais si on a aussi des sous répertoires plus bas, il faut alors modifier le code:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use File::Find;
  6.  
  7. my $level = -1;
  8. sub wanted {
  9.  if (-d) {
  10.    $level++;
  11.    if ((!/^.$/o)) {
  12.      $File::Find::prune = 1;
  13.    }
  14.    else {
  15.      $File::Find::prune = 0;
  16.    }
  17.    $level--;
  18.  }
  19.  if (-f) {
  20.    if (($level >= 2) and (/\.log$/o)) {
  21.      my $fsize = (stat($_))[7];
  22.      print "$fsize octets $File::Find::name\n"; # a adapter a son format voulu
  23.    }
  24.  }
  25. }
  26.  
  27.  
  28. File::Find::find({wanted => \&wanted,
  29.           preprocess =>  sub {$level++; return @_},
  30.           postprocess => sub {$level--}}, '/home/belette');


A+,


Message édité par gilou le 12-07-2011 à 13:15:26

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2088941
belette59
Posté le 12-07-2011 à 14:12:33  profilanswer
 

ok merci bcp !


---------------

n°2088945
gilou
Modérateur
Modzilla
Posté le 12-07-2011 à 14:24:25  profilanswer
 

Tiens au fait, tu peux éventuellement rajouter ceci à la fin du code:
print "Warning: unexpected ending level: $level\n" if ($level != -1);
Pour avertir, si on est pas revenu au niveau de départ à la fin du traitement, qu'il doit y avoir un problème.
A+,


Message édité par gilou le 12-07-2011 à 14:25:17

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --

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

  perl - lister les fichiers d'un rep

 

Sujets relatifs
Fichiers de moins de 24h triés par date ?Perl substitution fin de chaine
[OSX/Cocoa/ObjC] comment lister les process qui utilisent le réseau[Résolu] Création d'un tableau imbriqué à partir d'un tableau simple
[PowerShell] Renommer des fichiers PDF avec leurs métadonnées[Résolu] HTML::Parser, balises avec attribut
[BATCH] déplacer tous les fichiers d'un ensemble de répertoiresproblème pour travailler sur des fichiers textes en PHP
[ActiveState]Comment executer les commandes perl sous ActiveStateAccéder à des fichiers en écriture
Plus de sujets relatifs à : perl - lister les fichiers d'un rep


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