【问题标题】:Directory Handle in Perl Not Working ProperlyPerl 中的目录句柄无法正常工作
【发布时间】:2020-08-15 18:07:28
【问题描述】:

我正在尝试使用目录句柄读取 Perl 文件夹中的文件。该脚本能够显示文件名,但会引发两个错误:readdir() attempted on invalid dirhandle DIRclosedir() attempted on invalid dirhandle DIR

我正在调用一个子程序并传递两个值:

if($fileEnding eq "directory")
{
  print "$fileName is a directory\n";
  FolderInvestigator1($a, $fileName);
}

$a 保存通过命令行参数传递的目录名称及其路径。我将控制权传递给子程序。

下面是我的代码:-

sub FolderInvestigator1
{
  my $prevPath = shift;
  my $receivedFolder = shift;
  my $realPath = "$prevPath/$receivedFolder";
  my $path = File::Spec->rel2abs($realPath);
  print "$path\n";
  print "$receivedFolder Folder Received\n";
  opendir(DIR, $path) or die "You've Passed Invalid Directory as Arguments\n";  
  while(my $fileName = readdir DIR)
  {
    next if $fileName =~ /^\./;
    print "The Vacant Folder has $fileName file\n";
  }
  closedir(DIR);
}

这是我的完整代码:-

FirstResponder();

sub FirstResponder
{
  if (@ARGV == 0)
  {
    print "No Arguments Passed\n";
  }


else
{
    foreach my $a(@ARGV)
    {
        print "Investigating $a directory below:-\n";

        opendir(DIR, $a) or die "You've Passed Invalid Directory as Arguments\n";                       
        while(my $fileName = readdir DIR)
        {
            next if $fileName =~ /^\./;
            $ending = `file --mime-type $a/$fileName`;
            #print $ending;

            $fileEnding = `basename -s $ending`;                
            #print $fileEnding;
            chomp($fileEnding);
            #print $fileName,"\n";
            if($fileEnding eq "directory")
            {
                print "$fileName is a directory\n";
                FolderInvestigator1($a, $fileName);
            }

            else
            {
                CureExtensions($a, $fileName);
            }       
        }
        closedir(DIR);  
        my @files = glob("$a/*");
        my $size = @files;
        if($size == 0)
        {
            print "The $a is an empty directory\n";
        }   
    }
}#Foreach Ends Here..

}

请查看屏幕截图以了解更多信息!

即使我使路径正确,我也无法理解为什么目录句柄会引发错误。一些指导将不胜感激。

【问题讨论】:

  • 您正在第二次使用opendir(DIR, ...) ... closedir(DIR),然后才完成第一个句柄DIR。我建议你使用词法目录句柄而不是全局句柄。
  • 嗨@HåkonHægland。谢谢你的建议。我实际上是 Perl 的新手,因此任何有关 Lexical Dir Handles 的参考资料对我来说都是很棒的。谢谢!!
  • @Leon S Kennedy Lexial 文件和目录句柄只是您使用的标量变量,而不是DIR - 该变量获取对句柄的引用。使用类似my $dirhandle; opendir($dfirhandle, $a) or die;(或opendir(my $dirhandle, $a)...,如果你想花哨的话。my 使它成为词法(范围私有)。
  • 嗨@Silvar,感谢您的通知。我尝试使用它们。但是,错误仍然存​​在。实际上,我在最上面声明了它。顺便说一句,没有进展。
  • 你的脚本中有use strict; use warnings;吗?

标签: perl directory


【解决方案1】:

您的代码的问题在于您嵌套使用了裸字(全局)目录句柄 DIR,因此内循环在外循环完成之前关闭句柄:

opendir(DIR, $arg) or die "...";
while(my $fileName = readdir DIR) {
    # ... more code here
    opendir(DIR, $path) or die "...";
    while(my $file = readdir DIR) { 
        # ... more code here
    }
    closedir DIR;
}
closedir DIR;

这是一个示例,说明如何使用词法目录句柄 $DIR 而不是使用旧的全局裸字句柄 DIR 编写第一个循环:

use feature qw(say);
use strict;
use warnings;
use File::Spec;

FirstResponder();

sub FirstResponder {
    foreach my $arg (@ARGV) {
        print "Investigating $arg directory below:-\n";
        opendir(my $DIR, $arg) or die "You've Passed Invalid Directory as Arguments\n";
        my $size = 0;
        while(my $fileName = readdir $DIR) {
            next if $fileName =~ /^\./;
            my $path = File::Spec->catfile( $arg, $fileName );
            if( -d $path) {
                print "$fileName is a directory\n";
                say "FolderInvestigator1($arg, $fileName)"
            }
            else {
                say "CureExtensions($arg, $fileName)";
            }
            $size++;
        }
        closedir $DIR;  
        if($size == 0) {
            print "The $arg is an empty directory\n";
        }
    }
}

根据perldoc open

一种较旧的风格是使用裸词作为文件句柄,如

open(FH, "<", "input.txt")
   or die "Can't open < input.txt: $!";   

然后你可以使用 FH 作为文件句柄,关闭 FH 等等。请注意,它是一个全球性的 变量,所以不建议在新代码中使用这种形式。

另见:

【讨论】:

  • 嗨@Håkon Hægland,我实施了您的解决方案。错误消失了。你能告诉我catfilesay吗?我在终端里得到了这样的东西:-FolderInvestigator1(ImageFolder, Vacant)CureExtensions(ImageFolder, Paper.png)CureExtensions(ImageFolder, Stone.gif)。谢谢一百万!
  • 我使用了catfile,因为readdir 没有在文件名前添加目录名。然后catfile($dir, $filename) 将这两个部分连接起来。
猜你喜欢
  • 1970-01-01
  • 2019-06-20
  • 2014-07-17
  • 1970-01-01
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
相关资源
最近更新 更多