my $directory = shift @_;
my @dh;
my @files;
opendir (my $dh, $directory) or die "Couldn't open dir '$directory' : $!";
foreach my $file(readdir $dh) {
if( -f $file =~ /\.htm$/){
push(@files,$file);
}
elsif(-d $file){
push(@dh,$file);
$dh = shift @dh;
}
closedir ($dh);
}
我正在尝试让我的脚本进入一条路径,例如DATA /(这是成功的),但我希望我的脚本扫描该目录和子目录,然后如果任何文件匹配它将存储在@files
。
我正在尝试使用循环扫描所有子文件夹,例如
elsif(-d $file){
push(@dh,$file);
$dh = shift @dh;
}
在此声明中,$dh
将获取一个新的子目录名称以进行扫描
但是我得到了Segmentation fault
答案 0 :(得分:3)
这里有一些问题:
readdir
返回伪目录.
和..
,这些应该被忽略
readdir
仅返回文件名,而不返回文件的完整路径。因此-f
和-d
会在当前工作目录中查找具有此名称的条目,但可能找不到它
您正在将目录名称推送到@dh
,但将目录句柄$dh
移开,这不起作用
测试-f $file =~ /\.htm$/
首先将正则表达式应用于$file
变量,然后使用其结果(1
或""
)作为参数到-f
。这根本不是你想要的
一旦找到新目录就跳转到处理新目录,因此当前目录的其余部分不会被处理
这样的事情通常是使用File::Find
或递归子例程完成的,但你可以通过消除尾递归来做这样的事情。 注意它不需要考虑目录链接,并且如果找到目录链接就可以无限循环。这就是为什么最好使用一个具有所有这些扭结的模块。
use strict;
use warnings;
my @dh = @_;
my @files;
while (@dh) {
my $directory = shift @dh;
opendir my $dh, $directory or die "Couldn't open dir '$directory' : $!";
while (readdir $dh) {
next if /\A\.\.?\z/;
my $node= "$directory/$_";
if (-f $node and /\.html?$/i) {
push @files, $node;
}
elsif (-d $node) {
push @dh, $node;
}
}
}