Разработка

Будущая программа будет состоять из определения рекурсивной процедуры find и её вызовов:

sub find
{
	my $name=shift;
	❶ обработать имя $name
}

find($_) for @ARGV;
find('.') unless @ARGV;

Последняя строчка программы даст о себе знать, только если при запуске программы не были указаны параметры (массив @ARGV пуст).

Фрагмент разветвляет процедуру для трёх случаев: когда $name — имя директории, когда имя простого файла, и, наконец, когда $name не содержит ни того, ни другого (под этот случай попадает имя несуществующего файла). Нам потребуются средства, позволяющие по заданному имени определить, какому случаю оно соответствует.

Тут нам помогут встроенные операторы языка Perl -d и -f. Первый из них вычисляет истинное значение тогда и только тогда, когда его операнд — имя директории, второй, как нетрудно догадаться, когда операнд — имя обычного файла. Столь странный выбор имени операторов имеет причины, однако мы воздержимся от их объяснения. С учётом сказанного мы можем заменить фрагмент на следующий код:

Perl
if(-d $name) { ❷ обработать имя директории $name } elsif(-f $name) { print "$name\n"; } else { warn "$0: «$name»: $!\n"; }

Для получения оглавления директории используется примерно та же последовательность действий, что и при считывания содержимого файла: открытие и создание дескриптора директории — чтение в цикле из дескриптора — закрытие дескриптора. Открытие и закрытие осуществляется встроенными процедурами opendir и closedir. Для чтения из дескриптора служит процедура readdir.

Приступим к кодированию фрагмента . Объявим переменную $dir для дескриптора директории. Пользуясь тем, что в случае неудачи процедура opendir возвращает ложное значение, обработаем ошибку открытия директории:

Perl
my $dir; unless(opendir $dir, $name) { warn "$0: Невозможно открыть «$name»: $!\n"; return; }

Если открытие прошло успешно, займёмся обработкой в цикле объектов, расположенных непосредственно в директории. Особые случаи — директории . и .. — следует пропустить:

Perl
$name='' if $name eq '/'; for(readdir $dir) { next if $_ eq '.' or $_ eq '..'; find("$name/$_"); }

Первая строчка — наша маленькая хитрость, решающая проблему корневой директории.

Наконец, закрываем дескриптор:

Perl
closedir $dir;

Информатика-54© А. Н. Швец