sub dir_list1
{
$path=$_[0];
while(<$path/*>){
if (-f "$_"){
print "$path/$_\n";
}
else {
print "dir: $path/$_\n";# if ($entry ne "." && $entry ne "..");
dir_list1($_);
}
}
}
dir_list1(".");
当我执行上面的代码时,它首先打印当前目录的所有内容,然后继续列出子目录的内容。一旦遇到子目录,它是否应该进入子目录,列出内部文件并继续使用父文件夹?
感谢。
[编辑,以回应OrangeDog]
我在Windows上使用此代码。输出是这样的:
A.TXT
b.txt
导演:./ images周四
c.txt
d.txt
...
[然后列出图像文件夹]
./images/qwe.jpg
./images/asd.jpg
./images/zxc.jpg
...
答案 0 :(得分:4)
你在这里遇到了很多问题。这是一个实际可行的版本:
use strict;
use warnings;
sub dir_list1
{
my $path = $_[0];
for (<$path/*>) {
if (-f $_) {
print "$_\n";
}
else {
print "enter dir: $_\n";
dir_list1($_);
print "leave dir: $_\n";
}
}
}
dir_list1(".");
原始代码有问题:
use strict; use warnings;
$path
"$_"
)但基本问题是标量上下文中的glob运算符不能递归使用。它使用的迭代器与该特定代码行相关联。当你递归时,迭代器仍然从父目录返回文件名。
我将您的while
(标量上下文)更改为for
(列表上下文)。 for
循环生成完整的文件名列表,然后对其进行迭代,并且可以递归使用。
我假设你正在做这个学习练习。否则,您应该使用众多模块中的一个来查找文件。以下是部分列表:
我确信我忽略了更多。
答案 1 :(得分:1)
(我不打算将此作为答案发布,但是您要求在评论中更正版本的代码,所以...我的'更正'将是批发重写,作为避免轮子重新发明的哲学的一部分) 。
我会尽可能使用CPAN模块来处理这个问题。这有很好的副作用,例如在不同平台上使用路径分隔符做正确的事情,并将子例程中的行数减少1/3。
#!/usr/bin/perl
use strict;
use warnings;
use v5.10; # If you aren't using Perl 5.10 or newer, you should be. say alone makes tidier code
use Path::Class::Iterator;
sub dir_list1 {
my $path = shift;
my $it = Path::Class::Iterator->new(root => $path,breadth_first => 0);
until ($it->done) {
my $f = $it->next;
print 'dir: ' if $f->isa('Path::Class::Dir');
say $f;
}
}
dir_list1 "./";