Perl中的目录句柄无法正常工作 [英] Directory Handle in Perl Not Working Properly

查看:80
本文介绍了Perl中的目录句柄无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Directory Handle在Perl中的文件夹中读取文件.该脚本能够显示文件名,但会引发两个错误:尝试对无效的dirhandle DIR进行 readdir()和尝试对无效的dirhandle DIR 进行的 closedir()..>

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

  if($ fileEnding eq目录"){打印"$ fileName是目录\ n";FolderInvestigator1($ a,$ fileName);} 

$ a 包含目录名称及其通过命令行参数传递的路径.我正在将控件传递给子例程.

以下是我的代码:-

  sub FolderInvestigator1{我的$ prevPath = shift;我的$ receivedFolder = shift我的$ realPath ="$ prevPath/$ receivedFolder";我的$ path = File :: Spec-> rel2abs($ realPath);打印"$ path \ n";打印"$ receivedFolder Folder Received \ n";opendir(DIR,$ path)或死于您已将无效目录作为参数传递给\ n";while(我的$ fileName = readdir DIR){接下来如果$ fileName =〜/^\./;打印空文件夹有$ fileName文件\ n";}closeir(DIR);} 

这是我完整的代码:-

  FirstResponder();子FirstResponder{如果(@ARGV == 0){打印未传递参数\ n";}别的{foreach我的$ a(@ARGV){打印在下面调查$ a目录:-\ n";opendir(DIR,$ a)或死于您已将无效目录作为参数传递给\ n";while(我的$ fileName = readdir DIR){接下来如果$ fileName =〜/^\./;$ ending =`file --mime-type $ a/$ fileName`;#print $ end;$ fileEnding =`basename -s $ ending`;#print $ fileEnding;chomp($ fileEnding);#print $ fileName,"\ n";if($ fileEnding eq目录"){打印"$ fileName是目录\ n";FolderInvestigator1($ a,$ fileName);}别的{CureExtensions($ a,$ fileName);}}closeir(DIR);我的@files = glob("$ a/*");我的$ size = @files;if($ size == 0){打印"$ a是一个空目录\ n";}}} #Foreach在这里结束. 

}

请查看屏幕截图,以获取有关正在发生的事情的更多信息!

即使我将路径正确设置,我也无法理解目录句柄为何引发错误.一些指导将不胜感激.

解决方案

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

  opendir(DIR,$ arg)或死于"...";while(我的$ fileName = readdir DIR){#...更多代码在这里opendir(DIR,$ path)或死于"...";while(我的$ file = readdir DIR){#...更多代码在这里}封闭目录DIR;}封闭目录DIR; 

这里是一个示例,说明如何使用词法目录句柄 $ DIR 而不是使用遗留的全局裸字句柄 DIR :

 使用功能qw(say);使用严格使用警告;使用File :: Spec;急救人员();子FirstResponder {foreach我的$ arg(@ARGV){打印在下面调查$ arg目录:-\ n";opendir(我的$ DIR,$ arg)或死于您已将无效目录作为参数传递给\ n";我的$ size = 0;while(我的$ fileName = readdir $ DIR){接下来如果$ fileName =〜/^\./;我的$ path = File :: Spec-> catfile($ arg,$ fileName);if(-d $ path){打印"$ fileName是目录\ n";说"FolderInvestigator1($ arg,$ fileName)"}别的 {说"CureExtensions($ arg,$ fileName)";}$ size ++;}$ DIR;if($ size == 0){打印"$ arg是一个空目录\ n";}}} 

根据 perldoc open ,使用裸字文件句柄名称已过时并已弃用.>:

一种较旧的样式是使用裸词作为文件句柄,例如

  open(FH,<","input.txt")或死于无法打开< input.txt:$!"; 

然后,您可以将FH用作文件句柄,关闭FH等等.请注意,这是全球性的变量,因此不建议在新代码中使用这种形式.

另请参阅:

I am trying to read files inside a folder in Perl using Directory Handle. The script is able to show the file name but it is throwing two errors: readdir() attempted on invalid dirhandle DIR and closedir() attempted on invalid dirhandle DIR.

I am calling a subroutine and passing two values:

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

$a holds the directory name and its path which is being passed via command-line argument. I am passing the control to a subroutine.

Below is my code:-

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);
}

Here is my complete code:-

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..

}

Please see the screenshot for more information on what's going on!

I am not able to realize why Directory Handle is throwing error even though I made the path correct. Some guidance will be highly appreciated.

解决方案

The problem with your code is that you have a nested use of the bareword (global) dir handle DIR, and hence the inner loop closes the handle before the outer loop is finished:

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;

Here is an example of how you could write the first loop using a lexical dir handle $DIR instead of using a legacy global bareword handle 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";
        }
    }
}

The use of bareword filehandle names is old style and deprecated, according to perldoc open:

An older style is to use a bareword as the filehandle, as

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

Then you can use FH as the filehandle, in close FH and and so on. Note that it's a global variable, so this form is not recommended in new code.

See also:

这篇关于Perl中的目录句柄无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆