2009-10-02 10 views
9

Ich verwende diesen Code eine Liste aller Dateien in einem bestimmten Verzeichnis zu erhalten:Wie bekomme ich eine Liste aller Dateien mit einer bestimmten Erweiterung aus einem bestimmten Verzeichnis?

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

Wie ich diesen Code ändern kann oder etwas anhängen, so dass es nur für Textdateien und lädt nur schaut das Array mit dem Präfix des Dateinamens?

Beispiel Verzeichnisinhalt:

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

Beispiel Array Inhalt:

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

Denken Sie auch über eine lexikalische Variable für Ihr Verzeichnis handle: 'opendir my $ dirh, $ dir_path oder die" kann dir $ dir: $! ";' –

Antwort

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

keine Idee, wie man das Verzeichnis auch wieder ausgibt? Meine Ausgabe ist/dir/dir/dir/923847 ... wie kann ich nur die 923847 bekommen? – CheeseConQueso

+0

glob fügt hier zusätzliche Arbeit hinzu. Siehe http://stackoverflow.com/questions/1506801/what-reasons-are-there-to-prefer-glob-over-readdir-or-vie-versa-in-perl –

5

es genug ist, eine Zeile zu ändern:

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

Um nur die“zu erhalten. txt "-Dateien können Sie einen Dateitest verwenden ator (-f: reguläre Datei) und eine Regex.

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

Andernfalls können Sie für nur Textdateien suchen, Perl -T (ascii-Textdatei Test Operator) mit

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

-T ist zum Testen, ob Sie eine haben "Textdatei" – reinierpost

+0

Guter Punkt; von der Perldoc-Seite des Operators (http://perldoc.perl.org/5.8.8/perlfunc.html), "-T \t Datei ist eine ASCII-Textdatei (heuristische Schätzung)." wenn er nach ".txt" -Dateien sucht, wird dies genau das tun, was er fragt, ohne zu raten. –

3

Wenn Sie die neuen Funktionen von Perl 5.10 verwenden können, das ist, wie Ich würde es schreiben.

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 
} 

Oder wenn Sie sehr große Verzeichnisse haben, könnten Sie eine while Schleife verwenden.

{ 
    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

Nur diese verwenden:

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

Dies ist die einfachste Art, wie ich (wie in für Menschen lesbaren) unter Verwendung der glob-Funktion gefunden haben:

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

zusätzlich die „-f "stellt sicher, dass nur tatsächliche Dateien (und nicht Verzeichnisse) im Array gespeichert werden.

+0

Warum die Bearbeitung rückgängig machen? 'foreach $ file' ist nicht streng sicher. Wenn Sie 'foreach' zu 'for' bevorzugen, warum nicht' foreach my $ file'? –

+0

Warum jemand anderes altes Zeug bearbeiten, wenn Sie nicht wissen, warum es überhaupt veröffentlicht wurde? Hölle Ich weiß nicht einmal den Grund, warum ich dieses Stück Code vor drei Jahren geschrieben habe, aber da ich eine Gewohnheit habe, etwas zu testen, hat es wahrscheinlich gut funktioniert, und es gibt wahrscheinlich einen Grund, den ich nicht in der strengen hinzugefügt habe Erklärung entweder. Aber heißt das, ich sollte einfach eine zufällige Bearbeitung akzeptieren, und möchte ich sogar Zeit damit verbringen, es zu testen? Auf keinen Fall!Deshalb fand ich es viel sicherer, es einfach zurückzurollen. – Kebman

+0

Nur um es klar zu stellen, ich war es nicht, der es bearbeitet hat, ich sah nur den Schnitt und dachte, es hätte die Antwort verbessert. Es ist einfach komisch, dass Sie eine lexikalische '@Datei' und dann eine globale' $ -Datei' verwenden. –

Verwandte Themen