В вашей программе Perl есть особая проблема. Вы не используете аргумент, который передаете своей подпрограмме:
sub marin{
if (opendir DIR, $_){
marin $_;
} else {
push @files, $_;
}
closedir DIR;
}
Вы хотели использовать первый аргумент подпрограммы ($_[0]
), но вы используете переменную темы по умолчанию (* 1005)*) вместо. Поскольку в $_
нет значения, вы получаете сообщение об ошибке.
Вместо этого вы можете сказать:
opendir DIR, $_[0]
Но это немного уродливо. Это действительно одноэлементный доступ к массиву @_
, список аргументов подпрограммы. Вместо уродливой формы используйте присвоение списка, чтобы дать эти имена:
sub marin{
my( $file ) = @_;
if (opendir DIR, $file){
marin $file;
} else {
push @files, $file;
}
closedir DIR;
}
Следующая большая проблема заключается в том, что вы используете дескриптор файла голого слова (DIR
) в рекурсивной подпрограмме. По сути, это глобальная переменная, поэтому каждый раз, когда вы открываете ее, вы закрываете предыдущую. Вместо этого вы лексическая переменная. Если вы используете недавно объявленную лексическую переменную или переменную со значением undef, opendir
(или open
) поместит ссылку на открытый дескриптор файла в переменной. Теперь каждый дескриптор каталога является частным для подпрограммы call (не определение подпрограммы!). Для каждого уровня есть новый дескриптор каталога в дополнение ко всем другим, которые вы уже открыли:
sub marin{
my( $file ) = @_;
if (opendir my $dh, $file){
marin $file;
} else {
push @files, $file;
}
}
Теперь это должно приблизить вас к тому, что вы хотите. Это только первые проблемы, хотя. Каждый раз, когда вы звоните marin
, вам нужно решить, что он собирается вернуть, и как вы будете сообщать об этом на уровень выше. Пока вы работаете
У нас есть пример этой задачи в главе «Справочные трюки» в Intermediate Perl . Это похоже на этот пример:
use v5.10;
use Data::Dumper;
my $listing = marin( '/etc' );
sub marin {
my( $dir ) = @_;
if( opendir my $dh, $dir ) {
my %hash;
while( my $file = readdir($dh) ) {
next if $file eq '.' || $file eq '..';
next if -l $file; # symlinks can make a loop!
$hash{$file} = marin( "$dir/$file" )
}
return \%hash
}
return;
}
say Dumper( $listing );
Это выдает что-то вроде этого, где значение хеша undef указывает простой файл, а ссылочное значение хеша - это подкаталог:
$VAR1 = {
'php.ini.default-previous~orig' => undef,
'networks' => undef,
'csh.login~orig' => undef,
'rtadvd.conf~previous' => undef,
'group~previous' => undef,
'mach_init_per_user.d' => {},
'manpaths.d' => {
'Wireshark' => undef,
'MacGPG2' => undef
},
'rmtab' => undef,
'passwd' => undef,
'master.passwd' => undef,
...