如何读入Perl中目录的内容?

时间:2008-08-22 14:53:22

标签: perl file-io filesystems

如何让Perl将给定目录的内容读入数组?

Backticks可以做到,但是有一些使用'scandir'或类似术语的方法吗?

9 个答案:

答案 0 :(得分:51)

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:其他大多数答案都是有效的,但我想特别评论this answer,提供此解决方案:

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 中的所有内容,但'除外。和'..',因为很少希望在列表中使用它们。

答案 1 :(得分:13)

快速而肮脏的解决方案是使用glob

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

答案 2 :(得分: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;

答案 3 :(得分:7)

这将在一行中注意(注意末尾的'*'通配符)

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

答案 4 :(得分: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()函数提供了另一种更清晰的界面。

答案 5 :(得分: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";       
}

答案 6 :(得分:1)

与上述类似,但我认为最好的版本是(略微修改)来自“perldoc -f readdir”:

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

答案 7 :(得分:0)

来自: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";
}

以下示例(基于来自perldoc -f readdir的代码示例)获取以打开目录中的句点开头的所有文件(而不是目录)。文件名可在数组@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;

答案 8 :(得分:0)

您还可以使用流行的 Path::Tiny 模块中的 children 方法:

use Path::Tiny;
my @files = path("/path/to/dir")->children;

这会创建一个由 Path::Tiny 对象组成的数组,如果您想对文件进行操作,这些对象通常比文件名更有用,但如果您只需要名称:

my @files = map { $_->stringify } path("/path/to/dir")->children;