pas*_*636 1 recursion perl while-loop
我正在尝试以递归方式编写一个函数来搜索给定目录下的所有目录.
use strict;
use warnings;
sub printDir
{
my $root = shift;
opendir DIR, $root or die "can't open dir $root\n";
my $dir;
while ($dir = readdir DIR)
{
if (-d "$root/$dir" && "$dir" ne '.' && "$dir" ne '..')
{
print "$dir\n";
&printDir ("$root/$dir");
}
}
}
my $root = $ARGV[0];
printDir $root;
Run Code Online (Sandbox Code Playgroud)
如果目录层次结构如下:
A
/ \
B C
|
D
Run Code Online (Sandbox Code Playgroud)
搜索ABD后代码停止,不会搜索C. 代码有什么问题?
谢谢
您的目录句柄是全局的.
opendir DIR, $root or die "can't open dir $root\n";
Run Code Online (Sandbox Code Playgroud)
每次调用sub时它都会被覆盖.一旦完成一个调用并返回到最后一个范围,DIR仍然指向最后一个目录,该目录已经被读到最后,所以它不会读取任何其他内容并在最内层目录完成读取后立即完全停止.
您需要使用词法目录句柄.
opendir my $dh, $root or die "can't open dir $root\n";
while (my $dir = readdir $dh)
{
...
}
Run Code Online (Sandbox Code Playgroud)
也看到了例如在readdir中的perldoc.
这就是File :: Find的用途.
use File::Find;
use feature 'say';
my $root = $ARGV[0];
find(\&wanted, $root);
sub wanted {
say $File::Find::name if -d;
}
Run Code Online (Sandbox Code Playgroud)
问题出在以下几行:
opendir DIR, $root or die "can't open dir $root\n";
Run Code Online (Sandbox Code Playgroud)
您DIR对所有递归调用创建的所有目录句柄使用相同的符号(即).您需要确保每个调用都有自己的目录句柄.所以你将上面的行改为:
opendir my $dirh, $root or die "can't open dir $root\n";
Run Code Online (Sandbox Code Playgroud)
然后你还应该将while测试条件调整为
while ($dir = readdir $dirh)
Run Code Online (Sandbox Code Playgroud)
通常,在现代perl中,您应该始终将词法变量用于文件/目录句柄(例如open my $handle,'<','somefile').