readdir()尝试使用无效的dirhandle $ par_dir

时间:2016-06-03 09:00:26

标签: perl

我正在尝试在多个文件夹中执行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);

2 个答案:

答案 0 :(得分:1)

问题可能是您在$parent中指定的目录不存在。在继续使用句柄之前,您必须始终检查以确保对openopendir的调用成功

该路径01- DATA是可疑的。我希望01-DATA01- DATA只有一个空格,但很少使用多个空格,因为它们不可见且难以计算

以下是关于您的计划的其他一些想法

  • 必须始终 use strictuse 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;
相关问题