关于文件io:如何读取Perl中目录的内容?

关于文件io:如何读取Perl中目录的内容?

How do I read in the contents of a directory in Perl?

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

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


1
2
3
4
5
6
7
opendir(D,"/path/to/directory") || die"Can't open directory: $!\
"
;
while (my $f = readdir(D)) {
    print"\\$f = $f\
"
;
}
closedir(D);

编辑:抱歉,错过了"放入数组"部分:

1
2
3
4
5
6
7
8
9
10
11
my $d = shift;

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

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

EDIT2:大多数其他答案都是有效的,但是我想特别评论此答案,并提供以下解决方案:

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

首先,要说明自发布者以来没有做过的事情:它通过grep()从readdir()返回的列表传递给grep(),后者仅返回文件(与目录,设备,命名管道,等),并且不要以点开头(这会使列表名称@dots产生误导,但这是由于他从readdir()文档复制过来时所做的更改)。由于它限制了返回目录的内容,因此从技术上讲,我认为这不是一个正确的答案,但它说明了用于过滤Perl中文件名的常见用法,我认为这对记录很有用。另一个例子很多:

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

此代码段从目录句柄D中读取除"。"以外的所有内容。和'..',因为很少希望在清单中使用它们。


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

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

IO :: Dir很不错,并且还提供了一个绑定的哈希接口。

在perldoc中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,"\
"
;
}

因此您可以执行以下操作:

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

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

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

您可以使用DirHandle:

1
2
3
4
5
6
7
8
9
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()函数提供了一种更简洁的接口。


类似于上述内容,但我认为最好的版本是(略作修改)来自" perldoc -f readdir":

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

这是通过目录结构递归并从我编写的备份脚本中复制文件的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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\
";
        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 ."\
";
            copy( $filename, $destfile ) or print"
Error copying $filename: $!\
";
        }
    }
}

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

来自:http://perlmeme.org/faqs/file_io/directory_listing.html

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/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\
"
;
}

以下示例(基于来自perldoc -f readdir的代码示例)从打开目录中以句点开始获取所有文件(而非目录)。文件名位于数组@dots中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/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\
"
;
}

closedir(DIR);
exit 0;


closedir(DIR);
exit 0;

推荐阅读