Frage

Wie bringe ich Perl dazu, den Inhalt eines bestimmten Verzeichnisses in ein Array einzulesen?

Backticks kann es tun, aber gibt es eine Methode, die „scandir“ oder einen ähnlichen Begriff verwendet?

War es hilfreich?

Lösung

opendir(D, "/path/to/directory") || die "Can't open directory: $!\n";
while (my $f = readdir(D)) {
    print "\$f = $f\n";
}
closedir(D);

BEARBEITEN:Oh, tut mir leid, ich habe den Teil „in ein Array“ verpasst:

my $d = shift;

opendir(D, "$d") || die "Can't open directory $d: $!\n";
my @list = readdir(D);
closedir(D);

foreach my $f (@list) {
    print "\$f = $f\n";
}

EDIT2:Die meisten anderen Antworten sind gültig, aber ich wollte sie kommentieren diese Antwort konkret, in dem diese Lösung angeboten wird:

opendir(DIR, $somedir) || die "Can't open directory $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;

Um zunächst zu dokumentieren, was es tut, da das Poster dies nicht getan hat:es übergibt die zurückgegebene Liste von readdir() durch ein grep() Das gibt nur die Werte zurück, bei denen es sich um Dateien handelt (im Gegensatz zu Verzeichnissen, Geräten, Named Pipes usw.) und die nicht mit einem Punkt beginnen (was den Namen der Liste ergibt). @dots irreführend, aber das liegt an der Änderung, die er vorgenommen hat, als er es aus der readdir()-Dokumentation kopiert hat.Da es den Inhalt des zurückgegebenen Verzeichnisses einschränkt, glaube ich nicht, dass es technisch gesehen eine korrekte Antwort auf diese Frage ist, aber es veranschaulicht eine gängige Redewendung, die zum Filtern von Dateinamen verwendet wird Perl, und ich dachte, es wäre wertvoll, es zu dokumentieren.Ein weiteres häufig gesehenes Beispiel ist:

@list = grep !/^\.\.?$/, readdir(D);

Dieses Snippet liest alle Inhalte aus dem Verzeichnis-Handle D außer '.' ' und '..', da diese sehr selten in der Auflistung verwendet werden sollen.

Andere Tipps

Eine schnelle und schmutzige Lösung ist die Verwendung Kugel

@files = glob ('/path/to/dir/*');

IO::Dir ist nett und bietet auch eine gebundene Hash-Schnittstelle.

Aus dem Perldoc:

use IO::Dir;
$d = IO::Dir->new(".");
if (defined $d) {
    while (defined($_ = $d->read)) { something($_); }
    $d->rewind;
    while (defined($_ = $d->read)) { something_else($_); }
    undef $d;
}

tie %dir, 'IO::Dir', ".";
foreach (keys %dir) {
    print $_, " " , $dir{$_}->size,"\n";
}

Sie könnten also Folgendes tun:

tie %dir, 'IO::Dir', $directory_name;
my @dirs = keys %dir;

Dies wird in einer Zeile erledigt (beachten Sie den Platzhalter „*“ am Ende).

@files = </path/to/directory/*>;
# To demonstrate:
print join(", ", @files);

Du könntest benutzen DirHandle:

use DirHandle;
$d = new DirHandle ".";
if (defined $d)
{
    while (defined($_ = $d->read)) { something($_); }
    $d->rewind;
    while (defined($_ = $d->read)) { something_else($_); }
    undef $d;
}

DirHandle bietet eine alternative, sauberere Schnittstelle zum opendir(), closedir(), readdir(), Und rewinddir() Funktionen.

Hier ist ein Beispiel für die Rekursion durch eine Verzeichnisstruktur und das Kopieren von Dateien aus einem von mir geschriebenen Backup-Skript.

sub copy_directory {
my ($source, $dest) = @_;
my $start = time;

# get the contents of the directory.
opendir(D, $source);
my @f = readdir(D);
closedir(D);

# recurse through the directory structure and copy files.
foreach my $file (@f) {
    # Setup the full path to the source and dest files.
    my $filename = $source . "\\" . $file;
    my $destfile = $dest . "\\" . $file;

    # get the file info for the 2 files.
    my $sourceInfo = stat( $filename );
    my $destInfo = stat( $destfile );

    # make sure the destinatin directory exists.
    mkdir( $dest, 0777 );

    if ($file eq '.' || $file eq '..') {
    } elsif (-d $filename) { # if it's a directory then recurse into it.
        #print "entering $filename\n";
        copy_directory($filename, $destfile); 
    } else { 
        # Only backup the file if it has been created/modified since the last backup 
        if( (not -e $destfile) || ($sourceInfo->mtime > $destInfo->mtime ) ) {
            #print $filename . " -> " . $destfile . "\n";
            copy( $filename, $destfile ) or print "Error copying $filename: $!\n";
        } 
    } 
}

print "$source copied in " . (time - $start) . " seconds.\n";       
}

Ähnlich wie oben, aber ich denke, die beste Version ist (leicht modifiziert) von „perldoc -f readdir“:

opendir(DIR, $somedir) || die "can't opendir $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;

aus: http://perlmeme.org/faqs/file_io/directory_listing.html

#!/usr/bin/perl
use strict;
use warnings;

my $directory = '/tmp';

opendir (DIR, $directory) or die $!;

while (my $file = readdir(DIR)) {
    next if ($file =~ m/^\./);
    print "$file\n";
}

Das folgende Beispiel (basierend auf einem Codebeispiel von perldoc -f readdir) ruft alle Dateien (keine Verzeichnisse) beginnend mit einem Punkt aus dem geöffneten Verzeichnis ab.Die Dateinamen finden Sie im Array @dots.

#!/usr/bin/perl

use strict;
use warnings;

my $dir = '/tmp';

opendir(DIR, $dir) or die $!;

my @dots 
    = grep { 
        /^\./             # Begins with a period
    && -f "$dir/$_"   # and is a file
} readdir(DIR);

# Loop through the array printing out the filenames
foreach my $file (@dots) {
    print "$file\n";
}

closedir(DIR);
exit 0;


closedir(DIR);
exit 0;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top