1

我有一个文件夹,里面有很多子文件夹。在这些子文件夹中,我有许多要读取的 .html 文件。我已经编写了以下代码来做到这一点。它打开父文件夹和第一个子文件夹,它只打印一个 .html 文件。它显示错误:

NO SUCH FILE OR DIRECTORY

我不想更改整个代码。对现有代码的任何修改都对我有好处。

 use FileHandle;
 opendir PAR_DIR,"D:\\PERL\\perl_programes\\parent_directory";
 while (our $sub_folders = readdir(PAR_DIR))
 {
         next if(-d $sub_folders);

         opendir SUB_DIR,"D:\\PERL\\perl_programes\\parent_directory\\$sub_folders";
         while(our $file = readdir(SUB_DIR))
         {

       next if($file !~ m/\.html/i);
            print_file_names($file);    
         }
         close(FUNC_MODEL1);    
 }
 close(FUNC_MODEL);

  sub print_file_names()
  {
     my $fh1 = FileHandle->new("D:\\PERL\\perl_programes\\parent_directory\\$file")  
               or die "ERROR: $!"; #ERROR HERE 
     print("$file\n");
  }
4

6 回答 6

6

您发布的代码看起来过于复杂。查看File::Find::Rule,您可以用很少的代码完成大部分繁重的工作。

use File::Find::Rule;

my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->start("D:/PERL/perl_programes/parent_directory");

while( my $file = $finder->match()  ){
   print "$file\n";
}

我的意思是这不是很性感吗?!

一位用户评论说您可能希望仅使用 Depth=2 条目。

use File::Find::Rule;

my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->mindepth(2)->maxdepth(2)->start("D:/PERL/perl_programes/parent_directory");

while( my $file = $finder->match()  ){
   print "$file\n";
}

将应用此限制。

于 2009-05-18T17:28:22.533 回答
4

您没有$file在函数中提取提供的参数print_file_names()

它应该是:

sub print_file_names()
{
    my $file = shift;
    ...
}

顺便说一句,您-d在外循环中的测试看起来也错误。你说next if -d ...这意味着它会跳过目录的内部循环,这似乎与你所需要的完全相反。它工作的唯一原因是因为您正在测试$file的只是相对于路径的文件名,而不是完整的路径名。

另请注意:

  1. Windows 上的 Perl 可以很好地处理/路径分隔符
  2. 设置一次父目录,然后从中派生其他路径
  3. 使用opendir($scalar, $path)代替opendir(DIR, $path)

注意:未经测试的代码如下:

use strict;
use warnings;
use FileHandle;

my $parent = "D:/PERL/perl_programes/parent_directory";

my ($par_dir, $sub_dir);
opendir($par_dir, $parent);
while (my $sub_folders = readdir($par_dir)) {
    next if ($sub_folders =~ /^..?$/);  # skip . and ..
    my $path = $parent . '/' . $sub_folders;
    next unless (-d $path);   # skip anything that isn't a directory

    opendir($sub_dir, $path);
    while (my $file = readdir($sub_dir)) {
        next unless $file =~ /\.html?$/i;
        my $full_path = $path . '/' . $file;
        print_file_names($full_path);    
    }
    closedir($sub_dir);
}
closedir($par_dir);

sub print_file_names()
{
     my $file = shift;
     my $fh1 = FileHandle->new($file) 
           or die "ERROR: $!"; #ERROR HERE 
     print("$file\n");
 }
于 2009-05-18T15:00:24.593 回答
3

请开始放:

use strict;
use warnings;

在所有脚本的顶部,它将帮助您避免此类问题并使您的代码更具可读性。

你可以在这里阅读更多关于它的信息:Perlmonks

于 2009-05-18T15:12:47.953 回答
3

您将需要更改整个代码以使其健壮:

#!/usr/bin/perl

use strict;
use warnings;

use File::Find;

my $top = $ENV{TEMP};

find( { wanted => \&wanted, no_chdir=> 1 }, $top );

sub wanted {
    return unless -f and /\.html$/i;
    print $_, "\n";
}

__END__
于 2009-05-18T17:53:42.683 回答
1

您是否考虑过使用

文件::查找

于 2009-05-18T15:12:04.010 回答
0

这是一种不需要使用 File::Find 的方法:

首先打开根目录,使用readdir将所有子文件夹的名称存储在一个数组中;

然后,使用 foreach 循环。对于每个子文件夹,通过链接根目录和文件夹名称来打开新目录。仍然使用 readdir 将文件名存储在数组中。

最后一步是编写代码来处理这个 foreach 循环中的文件。

特别感谢给我这个想法的老师 :) 真的很好用!

于 2015-08-20T06:27:40.650 回答