37

Perl に特定のディレクトリの内容を配列に読み込ませるにはどうすればよいですか?

バックティックでもできますが、「 scandir」などを使った方法はありますか?

4

9 に答える 9

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

編集:ああ、申し訳ありませんが、「配列に」の部分を逃しました:

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:他のほとんどの回答は有効ですが、このソリューションが提供されているこの回答について具体的にコメントしたかったのです:

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

最初に、投稿者がそうしなかったので、それが何をしているのかを文書化します: readdir()から返されたリストを、 (ディレクトリ、デバイス、名前付きパイプなどではなく) ファイルである値のみを返すgrep()に渡しています。そしてそれはドットで始まっていません (リスト名@dotsが誤解を招きますが、これは readdir() のドキュメントからコピーしたときに彼が行った変更によるものです)。返されるディレクトリの内容が制限されるため、技術的にはこの質問に対する正しい答えではないと思いますが、Perlでファイル名をフィルタリングするために使用される一般的なイディオムを示しており、文書化する価値があると思いました。多く見られる別の例は次のとおりです。

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

このスニペットは、ディレクトリ ハンドル D から「.」を除くすべてのコンテンツを読み取ります。および '..' は、リストでの使用がほとんど望まれないためです。

于 2008-08-22T14:54:22.857 に答える
16

迅速で汚い解決策は、グロブを使用することです

@files = glob ('/path/to/dir/*');
于 2008-08-22T17:12:40.653 に答える
8

これにより、1行で実行されます(最後の「*」ワイルドカードに注意してください)

@files = </path/to/directory/*>;
# To demonstrate:
print join(", ", @files);
于 2008-08-22T15:27:15.633 に答える
8

IO :: Dirは素晴らしく、タイドハッシュインターフェイスも提供します。

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";
}

したがって、次のようなことができます。

tie %dir, 'IO::Dir', $directory_name;
my @dirs = keys %dir;
于 2008-08-22T16:09:34.360 に答える
5

DirHandleを使用できます:

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

DirHandleopendir()closedir()readdir()、およびrewinddir()関数への代替のよりクリーンなインターフェイスを提供します。

于 2008-09-01T14:52:11.160 に答える
1

上記と同様ですが、最良のバージョンは(わずかに変更された)「perldoc-freaddir」からのものだと思います。

opendir(DIR, $somedir) || die "can't opendir $somedir: $!";
@dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR);
closedir DIR;
于 2008-08-23T17:50:40.180 に答える
1

これは、ディレクトリ構造を繰り返して、私が作成したバックアップスクリプトからファイルをコピーする例です。

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";       
}
于 2008-08-22T15:36:02.163 に答える