Как читать имена файлов 10 одновременно, обрабатывать их, а затем читать следующие 10? - PullRequest
0 голосов
/ 25 февраля 2020

В Perl, как мне прочитать имена файлов в каталоге в массив Perl только 10 одновременно? Все решения для чтения каталогов, которые я нашел, похоже, читают только весь список файлов в массив одновременно, но я не хочу читать все файлы одновременно, потому что их могут быть миллионы, и я хочу уменьшить объем памяти.

Ответы [ 2 ]

2 голосов
/ 25 февраля 2020

opendir используется для чтения файла каталога по файлу. Тогда это просто вопрос буферизации результатов, пока вы не получите правильное число.

my $dir_qfn = "...";

my @buf;
opendir(my $dh, $dir_qfn)
   or die("Can't open directory \"$qfn\": $!\n");

while (defined( my $fn = readdir($dh) )) {
   my $qfn = "$dir_qfn/$fn";
   push @buf, $qfn;
   process_files(splice(@buf)) if @buf == 10;
}

process_files(@buf) if @buf;

process_file(splice(@buf)); это просто сокращение от process_file(@buf); @buf = ();


Это простой способ написания это, но что, если вы хотите устранить дублированный суб-вызов?

my $dir_qfn = "...";

my @buf;
opendir(my $dh, $dir_qfn)
   or die("Can't open directory \"$qfn\": $!\n");

while (1) {
   my $fn = readdir($dh);
   if (defined($fn)) {
      my $qfn = "$dir_qfn/$fn";
      push @buf, $qfn;
   }

   if (!defined($fn) || @buf == 10) {
      process_files(splice(@buf));
   }

   last if !defined($fn);
}

Это позволяет вам встроить process_file. Например, если у вас было

sub process_files {
   print("$_\n") for @_;
}

, теперь вы можете заменить

if (!defined($fn) || @buf == 10) {
   process_files(splice(@buf));
}

на

if (!defined($fn) || @buf == 10) {
   print("$_\n") for splice(@buf);
}
2 голосов
/ 25 февраля 2020

На странице readdir perldo c вы видите, что readdir возвращает одну запись каталога в скалярном контексте:

readdir DIRHANDLE

Возвращает следующая запись каталога для каталога, открытого opendir. Если используется в контексте списка, возвращает все остальные записи в каталоге. Если записей больше нет, возвращает неопределенное значение в скалярном контексте и пустой список в контексте списка.

Пример кода с той же страницы:

opendir(my $dh, $some_dir) || die "Can't open $some_dir: $!";
while (readdir $dh) {
    print "$some_dir/$_\n";
}
closedir $dh;

Обратите внимание, что это пример кода, и в реальном скрипте вам, вероятно, лучше обслужить явное объявление переменной для каталога, возвращаемого readdir, и не использовать специальную переменную $ _.

...