我正在尝试在多个文件夹中执行perl脚本,但我不明白为什么我在readdir()尝试无效的dirhandle $ par_dir时出现问题。 $ parent打印好,但$ par_dir打印如" GLOB(0x17e7a68)"。
知道为什么会这样吗?非常感谢!
这里是代码:
#!/usr/bin/perl
use warnings;
use Cwd;
use FileHandle;
use File::Glob;
my $parent = "/media/sequentia/NAS/projects/131-prgdb3/01- DATA/All_plant_genomes_proteomes";
my ($par_dir, $sub_dir);
opendir($par_dir, $parent);
print $parent."\n";
print $par_dir."\n";
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
print $path."\n";
chdir($path) or die;
@files = glob( $path. '/*' );
foreach $filename (@files){
print $filename ."\n";
system ("grep 'comment' PutativeGenes.txt | wc -l");
system ("grep 'class' PutativeGenes.txt | wc -l");
}
}
closedir($par_dir);
答案 0 :(得分:1)
问题可能是您在$parent
中指定的目录不存在。在继续使用句柄之前,您必须始终检查以确保对open
或opendir
的调用成功
该路径01- DATA
是可疑的。我希望01-DATA
或01- DATA
只有一个空格,但很少使用多个空格,因为它们不可见且难以计算
以下是关于您的计划的其他一些想法
您必须始终 use strict
和use warnings 'all'
位于您编写的每个Perl程序的顶部。这会提醒您注意许多您可能忽略的简单错误
您的陈述next if ( $sub_folders =~ /^..?$/ )
错误,因为必须转义这些点。因为它是丢弃任何长度为一个或两个字符的名称
如果您的路径确实包含空格,那么您需要use File::Glob ':bsd_glob'
,否则空格将被视为多个浮点模式之间的分隔符
您对foreach
中找到的每个文件或目录执行$path
循环,但您的system
调用不受该文件名称的影响,因此您'多次重拨同样的电话
值得注意的是glob
会为您搜索所有目录。我会写这样的东西
#!/usr/bin/perl
use strict;
use warnings 'all';
use File::Glob ':bsd_glob';
my $parent_dir = "/media/sequentia/NAS/projects/131-prgdb3/01-DATA/All_plant_genomes_proteomes";
print "$parent_dir\n";
while ( my $path = glob "$parent_dir/*" ) {
next unless -d $path;
print "$path\n";
chdir $path or die qq{Unable to chdir to "$path": $!};
while ( my $filename = glob "$path/*" ) {
next unless -f $filename;
print "$filename\n";
system "grep 'comment' PutativeGenes.txt | wc -l";
system "grep 'class' PutativeGenes.txt | wc -l";
}
}
答案 1 :(得分:0)
可能opendir()
未能提供无效的文件句柄(可能因为您尝试打开不存在的$parent
目录而失败)。
如果opendir
失败,则会返回false,$par_dir
保持不变为undef
。如果您尝试在未定义的文件句柄上调用readdir()
,则会收到运行时警告,如:
readdir() attempted on invalid dirhandle at ...
因此,您应该始终检查opendir
的返回代码。例如,你可以这样做:
opendir($par_dir, $parent) or die "opendir() failed: $!";
或查看有关此链接Does die have to be used if opening a file fails?
中的操作的更多建议请注意,您的代码可以使用File::Find::Rule
进行简化,例如:
my @dirs = File::Find::Rule
->directory->maxdepth(1)->mindepth(1)->in( $parent );
for my $dir (@dirs) {
say "$dir";
my @files = File::Find::Rule->file->maxdepth(1)->in( $dir );
say "--> $_" for @files;
}
或者,如果您不需要目录名称:
my @files = File::Find::Rule
->file->maxdepth(2)->mindepth(2)->in( $parent );
say for @files;