答案 0 :(得分:24)
使用-d
文件检查操作符:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $path = $ARGV[0];
die "Please specify which directory to search"
unless -d $path;
opendir( my $DIR, $path );
while ( my $entry = readdir $DIR ) {
next unless -d $path . '/' . $entry;
next if $entry eq '.' or $entry eq '..';
print "Found directory $entry\n";
}
closedir $DIR;
答案 1 :(得分:7)
如果您不需要遍历整个目录层次结构,File::Slurp比File::Find更容易使用。
use strict;
use warnings;
use File::Slurp qw( read_dir );
use File::Spec::Functions qw( catfile );
my $path = shift @ARGV;
my @sub_dirs = grep { -d } map { catfile $path, $_ } read_dir $path;
print $_, "\n" for @sub_dirs;
如果您确实需要遍历层次结构,请检查CPAN是否有File::Find
的更友好的替代方案。
File::Finder和File::Find::Rule是File::Find
的前端。
File::Find::Closures值得学习如何使用File::Find
以及如何使用my @sub_dirs = grep {-d} glob("$ARGV[0]/*");
写闭包。
File::Next使用迭代器方法进行目录遍历和 看起来很有希望,虽然我从未使用它。
最后,根据TIMTOWTDI的精神,这里有一些快速而肮脏的东西:
{{1}}
答案 2 :(得分:3)
use File::Spec::Functions qw( catfile );
my ($path) = @ARGV;
opendir my $DIR, $path
or die "Cannot open directory: '$path': $!";
while ( my $entry = readdir $DIR ) {
next if $entry =~ /\A\.\.?\z/;
next unless -d catfile $path, $entry;
print $entry, "\n";
}
closedir $DIR;
这对我有用。
答案 3 :(得分:1)
我在Windows XP下运行ActivePerl 5.10.1。如果我想获取根驱动器F下目录的所有名称,我将使用以下代码:
#!perl
opendir (DIR,'F:/');
my @folder = readdir(DIR);
foreach my $f (@folder)
{
next if ($f =~ /\./);
print "$f\n";
}
嗯,这通常有效,因为我的文件夹名称不包含点。否则就失败了。
好吧,似乎即使我的方法适用于我的情况,人们仍然会因为它有缺陷而投票。所以我必须使用官方方法,-d标志来检查文件是否是目录:
升级后的代码:
#!perl
use strict;
use warnings;
opendir (DIR, "F:/");
my @files = readdir(DIR);
my @dirs = grep { -d } @files;
print @dirs;
答案 4 :(得分:0)
答案 5 :(得分:0)
您可以使用find2perl将您的find命令转换为perl。有关详细信息,请参阅perldoc find2perl。
maxdepth的解决方法:(来自Randall的参考)
$ find2perl /home/path -type d -eval 'my $slashes = $File::Find::name =~ tr#/##;return $File::Find::prune = 1 if $slashes > 2;return if $slashes ==2'
代码:
use strict;
use File::Find ();
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;
sub wanted;
File::Find::find({wanted => \&wanted}, '/');
exit;
sub wanted {
eval { my $slashes = $File::Find::name =~ tr#/##;return $File::Find::prune = 1 if $slashes > 1;return if $slashes ==1 };
if ( $? == "0" && -d _ ){
print "$name --- \n";
}
}
输出
$ pwd
/temp
$ tree
.
|-- dir1
| |-- subdir1
| | |-- subsubdir1
| | `-- testsubdir1.txt
| `-- testdir1.txt
|-- dir2
| |-- subdir2
| | |-- subsubdir2
| | `-- testsubdir2.txt
| `-- testdir2.txt
|-- dir3
| `-- subdir3
| `-- subsubdir3
`-- test
9 directories, 5 files
$ perl perl.pl
/temp ---
/temp/dir3 ---
/temp/dir1 ---
/temp/dir2 ---
答案 6 :(得分:0)
使用File :: Find :: Rule
#!/usr/bin/perl --
use strict;
use warnings;
use Shell::Command qw( rm_rf touch mkpath );
use autodie;
use File::Find::Rule;
Main(@ARGV);
exit(0);
sub Main{
use autodie;
my $dir = "tmp";
mkdir $dir;
#~ chdir $dir;
mkpath "$dir/a/b/c/d";
mkpath "$dir/as/b/c/d";
mkpath "$dir/ar/b/c/d";
print `tree`;
print "---\n";
print "$_\n"
for File::Find::Rule->new->maxdepth(1)->directory->in($dir);
print "---\n";
print "$_\n"
for grep -d, glob "$dir/*"; ## use forward slashes, See File::Glob
#~ chdir "..";
rm_rf $dir;
}
__END__
.
|-- test.pl
`-- tmp
|-- a
| `-- b
| `-- c
| `-- d
|-- ar
| `-- b
| `-- c
| `-- d
`-- as
`-- b
`-- c
`-- d
13 directories, 1 file
---
tmp
tmp/a
tmp/ar
tmp/as
---
tmp/a
tmp/ar
tmp/as
或使用File :: Find :: Rule frontend findrule
$ findrule tmp -maxdepth ( 1 ) -directory
tmp
tmp/a
tmp/ar
tmp/as
答案 7 :(得分:-1)
您可以使用File :: Find。例如:
use File::Find ();
File::Find::find(\&wanted, '.');
sub wanted {
if (-d) {
print "$File::Find::name\n";
}
}
对于在'.'
下找到的每个文件,这将调用wanted
子例程。在子例程中,您可以使用-d
来检查目录。
File::Find:find
下降到指定目录下面树中的所有子目录。