如何读取Perl中的目录内容?
如何让Perl将给定目录的内容读入数组?
反引号可以做到这一点,但是有没有使用“scandir”或类似术语的方法?
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"; }
编辑2:大多数其他答案是有效的,但我想特别评论这个答案 ,在这个解决scheme提供:
opendir(DIR, $somedir) || die "Can't open directory $somedir: $!"; @dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR); closedir DIR;
首先,要logging下它做了什么,因为这个海报没有:它将readdir()的返回列表通过一个只返回文件值的grep() (与目录,设备,命名pipe道等相对)而不是以点开头(这使得列表名@dots
误导,但这是由于他从readdir()文档复制它所做的更改)。 由于它限制了它所返回的目录的内容,所以我不认为这个问题在技术上是正确的答案,但是它说明了一个常用的用来在Perl中过滤文件名的习惯用法,我认为这对于文档是有价值的。 另一个例子很多是:
@list = grep !/^\.\.?$/, readdir(D);
这段代码读取目录句柄D中除 “。” 以外的所有内容。 和'..',因为那些在上市中很less被期望被使用。
一个快速和肮脏的解决scheme是使用glob
@files = glob ('/path/to/dir/*');
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;
这将在一行(注意最后的'*'通配符)
@files = </path/to/directory/*>; # To demonstrate: print join(", ", @files);
你可以使用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
为opendir()
, closedir()
, readdir()
和rewinddir()
函数提供了一个更清晰的接口。
下面是一个通过目录结构recursion的例子,以及从我写的备份脚本复制文件。
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"; }
类似上面,但我认为最好的版本是(略有修改)“perldoc -f readdir”:
opendir(DIR, $somedir) || die "can't opendir $somedir: $!"; @dots = grep { (!/^\./) && -f "$somedir/$_" } readdir(DIR); closedir DIR;
来自: 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中find。
#!/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;