Рекурсивная обработка всех файлов каталога

Проблема

Требуется выполнить некоторую операцию с каждым файлом и подкаталогом некоторого каталога.

Решение

Воспользуйтесь стандартным модулем File::Find.
use File::Find;
sub process_file {
  # делаем то, что хотели
}
find(\&process_file, @DIRLIST);

Комментарий

Модуль File::Find обеспечивает удобные средства рекурсивной обработки файлов. Просмотр каталога и рекурсия организуются без вашего участия. Достаточно передать find ссылку на функцию и список каталогов. Для каждого файла в этих каталогах find вызовет заданную функцию.
Перед вызовом функции find переходит в указанный каталог, имя которого по отношению к начальному каталогу хранится в переменной $File::Find::dir. Переменной $_ присваивается базовое имя файла, а полный путь к этому файлу находится в переменной $File::Find::name. Ваша программа может присвоить $File::Find::prune истинное значение, чтобы функция find не спускалась в только что просмотренный каталог.
Использование File::Find демонстрируется следующим простым примером. Мы передаем find анонимную подпрограмму, которая выводит имя каждого обнаруженного файла и добавляет к именам каталогов /:
@ARGV = qw(.) unless @ARGV;
use File::Find:
find sub { print $File::Find::name, -d && '/', "\n" }, @ARGV;
Для вывода / после имен каталогов используется оператор проверки -d, который при отрицательном результате возвращает пустую строку ' '.
Следующая программа выводит суммарный размер всего содержимого каталога. Она передает find анонимную подпрограмму для накопления текущей суммы всех рассмотренных ей файлов. Сюда входят не только обычные файлы, но и все типы индексных узлов, включая размеры каталогов и символических ссылок. После выхода из функции find программа выводит накопленную сумму.
use File::Find:
@ARGV = ('.') unless (3ARGV;
my $sum = 0;
find sub { $sum += -s }, @ARGV;
print "@ARGV contains $sum bytes\n";
Следующий фрагмент ищет самый большой файл в нескольких каталогах:
use File::Find;
@ARGV = ('.') unless @ARGV;
my ($saved_size, $saved_name) = (-1, '');
sub biggest {
  return unless -f && -s _ > $saved_size;
  $saved_size = -s _;
  $saved_name = $File::Find::name;
}
find(\&biggest, @ARGV);
print "Biggest file $saved_name in @ARGV is $saved_size bytes long.\n";
Переменные $saved_size и $saved_name используются для хранения имени и размера самого большого файла. Если мы находим файл, размер которого превышает размер самого большого из просмотренного до настоящего момента, сохраненное имя и размер заменяются новыми значениями. После завершения работы find выводится имя и размер самого большого файла в весьма подробном виде. Вероятно, более практичная программа ограничится выводом имени файла, его размера или и того и другого. На этот раз мы воспользовались именованной функцией вместо анонимной, поскольку она получилась относительно большой.
Программу нетрудно изменить так, чтобы она находила файл, который изменялся последним:
use File::Find;
@ARGV = ('.') unless @ARGV;
my ($age, $name);
sub youngest {
  return if defined $age && $age > -M;
  $age = (stat(_))[9];
  $name = $File::Find::name;
}
find(\&youngest, @ARGV);
print "$name " . scalar(localtime($age)) . "\n";

См. также




2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: