2009-10-02 17 views
9

Sto usando questo codice per ottenere un elenco di tutti i file in una directory specifica:Come posso ottenere un elenco di tutti i file con una determinata estensione da una directory specifica?

opendir DIR, $dir or die "cannot open dir $dir: $!"; 
my @files= readdir DIR; 
closedir DIR; 

Come posso modificare il codice o aggiungere qualcosa ad esso in modo che appaia solo per i file di testo e solo carichi la matrice con il prefisso del nome file?

contenuto della directory Esempio:

. 
.. 
923847.txt 
98398523.txt 
198.txt 
deisi.jpg 
oisoifs.gif 
lksdjl.exe 

Esempio contenuto dell'array:

files[0]=923847 
files[1]=98398523 
files[2]=198 
+0

Considerate anche l'utilizzo di una variabile lessicale per il vostro handle di directory: 'opendir my $ dirh, $ dir_path o die" non può aprire dir $ dir: $! ";' –

risposta

10
my @files = glob "$dir/*.txt"; 
for (0..$#files){ 
    $files[$_] =~ s/\.txt$//; 
} 
+0

qualche idea su come regex anche la directory? il mio output è/dir/dir/dir/923847 ... come posso ottenere il 923847? – CheeseConQueso

+0

glob aggiunge lavoro extra qui. Vedi http://stackoverflow.com/questions/1506801/what-reasons-are-there-to-prefer-glob-over-readdir-or-vice-versa-in-perl –

5

è sufficiente a cambiare una sola riga:

my @files= map{s/\.[^.]+$//;$_}grep {/\.txt$/} readdir DIR; 
2

per ottenere solo il". txt ", puoi usare un file test oper ator (-f: file normale) e una regex.

my @files = grep { -f && /\.txt$/ } readdir $dir; 

In caso contrario, è possibile cercare i file di testo solo, utilizzando (operatore di verifica file di testo ASCII) -T di perl

my @files = grep { -T } readdir $dir; 
+0

-T è per testare se si dispone di un "file di testo" – reinierpost

+0

Buon punto; dalla pagina perldoc sull'operatore (http://perldoc.perl.org/5.8.8/perlfunc.html), "-T \t File è un file di testo ASCII (ipotesi euristica)." se sta cercando file ".txt", questo farà esattamente quello che chiede senza indovinare. –

3

Se è possibile utilizzare le nuove funzionalità di Perl 5.10, questo è il modo Lo scriverei

use strict; 
use warnings; 
use 5.10.1; 
use autodie; # don't need to check the output of opendir now 

my $dir = "."; 

{ 
    opendir my($dirhandle), $dir; 
    for(readdir $dirhandle){ # sets $_ 
    when(-d $_){ next } # skip directories 
    when(/^[.]/){ next } # skip dot-files 

    when(/(.+)[.]txt$/){ say "text file: ", $1 } 
    default{ 
     say "other file: ", $_; 
    } 
    } 
    # $dirhandle is automatically closed here 
} 

O se avete grosse directory, è possibile utilizzare un ciclo while.

{ 
    opendir my($dirhandle), $dir; 
    while(my $elem = readdir $dirhandle){ 
    given($elem){ # sets $_ 
     when(-d $_){ next } # skip directories 
     when(/^[.]/){ next } # skip dot-files 

     when(/(.+)[.]txt$/){ say "text file: ", $1 } 
     default{ 
     say "other file: ", $_; 
     } 
    } 
    } 
} 
1

Basta usare questo:

my @files = map {-f && s{\.txt\z}{} ? $_ :()} readdir DIR; 
1

Questo è il modo più semplice che ho trovato (come nel leggibile) utilizzando la funzione glob:

# Store only TXT-files in the @files array using glob 
my @files = grep (-f ,<*.txt>); 
# Write them out 
foreach $file (@files) { 
    print "$file\n"; 
} 

Inoltre il "-f "assicura che solo i file effettivi (e non le directory) siano memorizzati nell'array.

+0

Perché ripristinare la modifica? 'foreach $ file' non è strettamente sicuro. Se preferisci 'foreach' a' for', perché non 'foreach my $ file'? –

+0

Perché modificare qualcun altro vecchie cose quando non si conosce il motivo per cui è stato pubblicato in primo luogo? Non conosco nemmeno il motivo per cui ho scritto questo pezzo di codice più di tre anni fa, ma dato che ho l'abitudine di provare qualcosa, probabilmente ha funzionato bene, e probabilmente c'è un motivo per cui non ho aggiunto il rigore dichiarazione o. Tuttavia, ciò significa che dovrei solo accettare una modifica a caso, e voglio anche passare il tempo a provarlo? Diavolo, no!Questo è il motivo per cui ho trovato molto più sicuro il rollback. – Kebman

+0

Giusto per essere chiari, non sono stato io a modificarlo, ho appena visto la modifica e ho pensato di aver migliorato la risposta. È strano che tu usi un '' file' lessicale e poi un 'file $ globale '. –

Problemi correlati