Получение имен и размеров всех файлов в подкаталогах с использованием PERL - PullRequest
0 голосов
/ 16 октября 2018

Я написал процедуру для чтения всех имен и размеров файлов, содержащихся в двух папках, и всех их подпапок.Имена корневых папок указываются в аргументах командной строки, и каждая папка обрабатывается в цикле for, а детали выводятся в отдельный файл для каждой из двух папок.Но я обнаружил, что выводятся только имена файлов / размеры файлов в двух корневых папках, я не могу перейти в подпапки и повторить процесс, поэтому файлы в подкаталогах игнорируются.Трассировки отладки показывают, что команда chdir никогда не выполняется, поэтому что-то не так с моей оценкой, но я не вижу, что это такое.Код выглядит следующим образом:

#!/usr/bin/perl
#!/usr/local/bin/perl

use strict;
use warnings;

my $dir = $ARGV[0];
opendir(DIR, $dir) or die "Could not open directory '$dir' $!";
my @subdirs = readdir(DIR) or die "Unable to read directory '$dir': $!";

for (my $loopcount = 1; $loopcount < 3; $loopcount = $loopcount + 1) {
    my $filename = 'FileSize_'.$dir.'.txt';
    open (my $fh, '>', $filename) or die "Could not open file '$filename' $!";      
    for my $subdir (sort @subdirs) {
        unless (-d $subdir) {
            # Ignore Sub-Directories in this inner loop
            # only process files
            # print the file name and file size to the output file
            print "Processing files\n";
            my $size = -s "$dir/$subdir";
            print $fh "$subdir"," ","$size\n";
        }
        elsif (-s "$dir/$subdir") {
        # We are here because the entry is a sub-folder and not a file
        # if this sub-folder is non-zero size, i.e has files then
        # change to this directory and repeat the outer for loop
            chdir $subdir;
            print "Changing to directory $subdir\n";
            print "Processing Files in $subdir\n";
        };
    }
    # We have now processed all the files in First Folder and all it's subdirecorries
    # Now assign the second root directory to the $dir variable and repeat the loop
    print "Start For Next Directory\n";
    $dir = $ARGV[1];
    opendir(DIR, $dir) or die "Could not open directory '$dir' $!";
    @subdirs = readdir(DIR) or die "Unable to read directory '$dir': $!";;
}
exit 0;

Вызов командной строки: «perl FileComp.pl DiskImage DiskImage1», но выводятся только имена файлов и размеры файлов в корневых папках DiskImage и DiskImage1, все файлыв подпапках игнорируются.Код для перехода в условие «elseif» никогда не выполняется, и код никогда не выполняется, поэтому там есть ошибка.Заранее спасибо за любой совет.

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Гораздо проще сделать подобную логику без изменения каталогов, но если вы используете File :: chdir или File :: pushd , чтобы вы могли вернуться в предыдущий каталог, когдавыход из этой области.Однако эту проблему гораздо проще решить с помощью рекурсивного итератора, например Path :: Iterator :: Rule , который обрабатывает логику подкаталога:

use strict;
use warnings;
use Path::Iterator::Rule;
use Path::Tiny;

my $rule = Path::Iterator::Rule->new->not_directory;
foreach my $dir (@ARGV) {
    my $fh = path("FileSize_$dir.txt")->openw;
    my $next = $rule->iter($dir);
    while (defined(my $item = $next->())) {
        my $size = -s $item;
        print $fh "$item $size\n";
    }
}

В качестве альтернативы вы можете использовать visitor обратный вызов, который получает полный путь (для файловых операций) и базовое имя каждого элемента:

my $rule = Path::Iterator::Rule->new->not_directory;
foreach my $dir (@ARGV) {
    my $fh = path("FileSize_$dir.txt")->openw;
    $rule->all($dir, {visitor => sub {
        my ($path, $basename) = @_;
        my $size = -s $path;
        print $fh "$basename $size\n";
    }});
}
0 голосов
/ 16 октября 2018

Эта проверка, скорее всего, всегда будет неправильной, потому что вы смотрите не на ту вещь.

   unless (-d $subdir) {

$subdir - это имя файла файла или каталога внутри $dir, поэтому для доступа к нему вамвам нужно использовать полный относительный путь $dir/$subdir, как вы делаете здесь:

        my $size = -s "$dir/$subdir";

У вас также будут проблемы, если вы исправите эту проверку unless, потому что выполнение chdir также будетвызывать проблемы во время чтения содержимого $dir, поэтому вы окажетесь не в том месте, чтобы увидеть более поздние экземпляры $dir/$subdir.

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