Perl 中的目录句柄无法正常工作
Posted
技术标签:
【中文标题】Perl 中的目录句柄无法正常工作【英文标题】:Directory Handle in Perl Not Working Properly 【发布时间】:2020-08-15 18:07:28 【问题描述】:我正在尝试使用目录句柄读取 Perl 文件夹中的文件。该脚本能够显示文件名,但会引发两个错误:readdir() attempted on invalid dirhandle DIR
和 closedir() 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;
吗?
【参考方案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 等等。请注意,它是一个全球性的 变量,所以不建议在新代码中使用这种形式。
另见:
Why does Perl open() documentation use two different FILEHANDLE style? Don't Open Files in the old way【讨论】:
嗨@Håkon Hægland,我实施了您的解决方案。错误消失了。你能告诉我catfile
和say
吗?我在终端里得到了这样的东西:-FolderInvestigator1(ImageFolder, Vacant)
CureExtensions(ImageFolder, Paper.png)
CureExtensions(ImageFolder, Stone.gif)
。谢谢一百万!
我使用了catfile
,因为readdir
没有在文件名前添加目录名。然后catfile($dir, $filename)
将这两个部分连接起来。以上是关于Perl 中的目录句柄无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Perl 的 system() 的输出重定向到文件句柄?