打开目录,然后扫描父目录以查找匹配的文件

时间:2013-05-04 04:36:49

标签: perl

    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

1 个答案:

答案 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;
    }
  }

}