2012-03-07 7 views
6
opendir(DIR,"$pwd") or die "Cannot open $pwd\n"; 
    my @files = readdir(DIR); 
    closedir(DIR); 
    foreach my $file (@files) { 
     next if ($file !~ /\.txt$/i); 
     my $mtime = (stat($file))[9]; 
     print $mtime; 
     print "\n"; 
    } 

In sostanza, voglio prendere nota del timestamp di tutti i file txt in una directory. Se c'è una sottodirectory, voglio includere anche i file in quella sottodirectory.Come attraversare tutti i file in una directory; se ha sottodirectory, voglio attraversare i file anche nelle sottodirectory

Qualcuno può aiutarmi a modificare il codice sopra in modo che includa anche sottodirectory.

se sto usando il codice qui sotto in Windows iam ottenendo timestamp di tutti i file che si trovano in cartelle anche fuori dalla mia cartella

my @dirs = ("C:\\Users\\peter\\Desktop\\folder"); 
    my %seen; 
    while (my $pwd = shift @dirs) { 
      opendir(DIR,"$pwd") or die "Cannot open $pwd\n"; 
      my @files = readdir(DIR); 
      closedir(DIR); 
      #print @files; 
      foreach my $file (@files) { 
        if (-d $file and !$seen{$file}) { 
          $seen{$file} = 1; 
          push @dirs, "$pwd/$file"; 
        } 
        next if ($file !~ /\.txt$/i); 
        my $mtime = (stat("$pwd\$file"))[9]; 
        print "$pwd $file $mtime"; 
        print "\n"; 
      } 
    } 

risposta

8
use warnings; 
use strict; 

my @dirs = ("."); 
my %seen; 
while (my $pwd = shift @dirs) { 
     opendir(DIR,"$pwd") or die "Cannot open $pwd\n"; 
     my @files = readdir(DIR); 
     closedir(DIR); 
     foreach my $file (@files) { 
       if (-d $file and ($file !~ /^\.\.?$/) and !$seen{$file}) { 
         $seen{$file} = 1; 
         push @dirs, "$pwd/$file"; 
       } 
       next if ($file !~ /\.txt$/i); 
       my $mtime = (stat("$pwd/$file"))[9]; 
       print "$pwd $file $mtime"; 
       print "\n"; 
     } 
} 
+0

Il vecchio modo robusto ... ben fatto senza ricorsione =) – Ouki

+1

'$ file! ~ /^\.*$/' è '$ file = ~ /[^.]/'. Ma sono stato severamente rimproverato in passato per escludere i nomi che sono solo tre punti o più, in quanto sono nomi validi per i file Linux. Quindi il test * dovrebbe * essere '$ file! ~ /^\.\.?$/' – Borodin

+0

@perreal se voglio aprire file e cercare una stringa particolare nel file e separare tali file, sto pensando di farlo con OPEN INPUT, $ file, poi $ lines = quindi seraching su di esso, va bene? o c'è un altro modo semplice – Peter

1

È possibile utilizzare la ricorsione: definire una funzione che passa attraverso i file e si invita le directory. Quindi chiama la funzione nella directory principale.

Vedere anche File::Find.

+0

come distinguere tra un file e una directory all'interno di una directory – Peter

+1

@Peter: utilizzare gli operatori '-d' e' -f', documentati [qui] (http://perldoc.perl.org/functions/- X.html) – Borodin

11

File::Find è meglio per questo. È un modulo principale quindi non ha bisogno di installazione. Questo codice fa l'equivalente di quello che sembrano avere in mente

use strict; 
use warnings; 

use File::Find; 

find(sub { 
    if (-f and /\.txt$/) { 
    my $mtime = (stat _)[9]; 
    print "$mtime\n"; 
    } 
}, '.'); 

dove '.' è la radice dell'albero di directory da sottoporre a scansione; potresti usare $pwd qui se lo desideri. All'interno della subroutine, Perl ha fatto un chdir nella directory in cui ha trovato il file, $_ è impostato sul nome file e $File::Find::name è impostato sul nome file completo compreso il percorso.

+1

[Non tutti saranno d'accordo con voi] (https://www.socialtext.net/perl5/alternatives_to_file_find) su File :: Trova la cosa migliore. – salva

+1

File :: Trova è lento e l'API è frustrante, ma penso che sia l'ideale per qualcosa di banale come questo. Mi piacerebbe sentire cosa c'è contro qualcuno. – Borodin

+0

@salva Commento molto vecchio, lo so, ma il link ora punta a una pagina di accesso. –