如何在Perl中读取多个目录和子目录的内容?
我有一个文件夹,里面有很多子文件夹。在这些子文件夹中,我有许多.html文件要读取。为此,我编写了以下代码。它打开父文件夹和第一个子文件夹,只打印一个.html文件。它显示错误:如何在Perl中读取多个目录和子目录的内容?,perl,recursion,readdir,Perl,Recursion,Readdir,我有一个文件夹,里面有很多子文件夹。在这些子文件夹中,我有许多.html文件要读取。为此,我编写了以下代码。它打开父文件夹和第一个子文件夹,只打印一个.html文件。它显示错误: NO SUCH FILE OR DIRECTORY 我不想更改整个代码。对现有代码的任何修改都将对我有利 use FileHandle; opendir PAR_DIR,"D:\\PERL\\perl_programes\\parent_directory"; while (our $sub_folders =
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");
}
您没有在
print\u file\u names()
函数中提取提供的$file
参数
应该是:
sub print_file_names()
{
my $file = shift;
...
}
顺便说一句,你在外循环中的-d
测试看起来也错了。你说的是下一个if-d…
,这意味着它将跳过目录的内循环,这似乎与你的要求完全相反。它工作的唯一原因是因为您正在测试$file
,它只是相对于路径的文件名,而不是完整的路径名
另请注意:
/
作为路径分隔符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");
}
您没有在
print\u file\u names()
函数中提取提供的$file
参数
应该是:
sub print_file_names()
{
my $file = shift;
...
}
顺便说一句,你在外循环中的-d
测试看起来也错了。你说的是下一个if-d…
,这意味着它将跳过目录的内循环,这似乎与你的要求完全相反。它工作的唯一原因是因为您正在测试$file
,它只是相对于路径的文件名,而不是完整的路径名
另请注意:
/
作为路径分隔符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");
}
你考虑过使用吗
您考虑过使用 请开始放:
use strict;
use warnings;
在所有脚本的顶部,它将帮助您避免此类问题,并使代码更具可读性
您可以在此处阅读更多信息:请开始放置:
use strict;
use warnings;
在所有脚本的顶部,它将帮助您避免此类问题,并使代码更具可读性
您可以在此处阅读更多信息:您发布的代码看起来过于复杂。看看吧,你可以用很少的代码完成大部分繁重的工作
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";
}
将应用此限制 您发布的代码看起来过于复杂。看看吧,你可以用很少的代码完成大部分繁重的工作
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";
}
将应用此限制 您需要更改整个代码以使其健壮:
#!/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__
您需要更改整个代码以使其健壮:
#!/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__
这里有一种方法不需要使用File::Find: 首先打开根目录,使用readdir将所有子文件夹的名称存储在一个数组中 然后,使用foreach循环。对于每个子文件夹,通过链接根目录和文件夹名称打开新目录。仍然使用readdir将文件名存储在数组中 最后一步是编写代码来处理这个foreach循环中的文件
特别感谢我的老师给了我这个想法:)它真的很好用 这里有一种方法不需要使用File::Find: 首先打开根目录,使用readdir将所有子文件夹的名称存储在一个数组中 然后,使用foreach循环。对于每个子文件夹,通过链接根目录和文件夹名称打开新目录。仍然使用readdir将文件名存储在数组中 最后一步是编写代码来处理这个foreach循环中的文件
特别感谢我的老师给了我这个想法:)它真的很好用 提示:更喜欢使用“我的”而不是“我们的”,并使用-w选项运行perl(如果可能的话,使用strict)。这将有助于更早地显示此错误:使用“my”但不使用strict,它会警告您“$file”未定义,使用strict,它会在运行之前终止,并说“$file”未声明。提示:更喜欢使用“my”而不是“our”,并使用-w选项运行perl(如果可能的话,还可以使用“use strict”)。这将有助于更早地显示此错误:使用“my”但不使用strict,它会警告您“$file”未定义,使用strict,它会在运行之前停止运行,说“$file”未声明。name(*.html)与他的正则表达式不匹配。幸运的是,name()接受正则表达式和全局表达式。我已经修复了匹配的条件。这将在树中查找级别1和3+的文件(如果存在),这与他的要求相反…@Alnitak:为搜索设置mindepth和maxdepth很容易。name(*.html)与他的正则表达式不匹配。幸运的是,name()接受正则表达式和全局表达式。我已经修正了匹配的条件。这将在树中找到1级和3+级的文件(如果存在的话),这与他的要求相反…@Alnitak:为搜索设置mindepth和maxdepth很容易。对于那些因为我没有使用File::find-a而否决我的人,我正在向他展示如何正确使用opendir等,b)他只指定了两个级别的目录,所有文件都是2级的。而且-错误甚至不在opendir代码中,而是在print_file_names()中!!我给你投了正确的票