Дескриптор каталога в Perl не работает должным образом - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь прочитать файлы в папке в Perl, используя Directory Handle. Сценарий может отображать имя файла, но выдает две ошибки: 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..

}

Пожалуйста, смотрите скриншот для получения дополнительной информации о том, что происходит!

enter image description here

Я не могу понять, почему Directory Handle выдает ошибку, хотя Я сделал правильный путь. Некоторые рекомендации будут высоко оценены.

1 Ответ

2 голосов
/ 01 мая 2020

Проблема с вашим кодом заключается в том, что вы используете вложенный (глобальный) дескриптор dir голого слова DIR, и, следовательно, внутренний l oop закрывает дескриптор до завершения внешнего l oop:

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;

Вот пример того, как вы могли бы написать первый l oop, используя лексический указатель 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";
        }
    }
}

Использование имен файловых дескрипторов без слов является старым стилем и устарело, согласно perldo c open :

Более старый стиль - использование голого слова в качестве дескриптора файла, так как

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

Затем вы можете использовать FH в качестве дескриптора файла, в закрытом FH и так далее. Обратите внимание, что это глобальная переменная, поэтому эта форма не рекомендуется в новом коде.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...