Я хочу считать каталог рекурсивно для печати структуры данных в СТРАНИЦЕ HTML с Шаблоном:: Инструментарий. Но я зависаю в том, как сохранить Пути и Файлы в форме, которая может быть считана наше легкое.
Моя идея запускается как это
sub list_dirs{
my ($rootPath) = @_;
my (@paths);
$rootPath .= '/' if($rootPath !~ /\/$/);
for my $eachFile (glob($path.'*'))
{
if(-d $eachFile)
{
push (@paths, $eachFile);
&list_dirs($eachFile);
}
else
{
push (@files, $eachFile);
}
}
return @paths;
}
Как я мог решить эту проблему?
Это должно помочь
use strict;
use warnings;
use File::Find qw(finddepth);
my @files;
finddepth(sub {
return if($_ eq '.' || $_ eq '..');
push @files, $File::Find::name;
}, '/my/dir/to/search');
Я думаю, у вас есть проблема в следующей строке вашего кода
for my $eachFile (glob($path.'*'))
Вы меняете переменную $ path на $ rootpath.
Путь будет сохранен правильно.
Ответ mdom объясняет, почему ваша первая попытка не удалась. Я также предлагаю вам рассмотреть более удобные альтернативы File :: Find
. У CPAN есть несколько вариантов. Вот один.
use strict;
use warnings;
use File::Find::Rule;
my @paths = File::Find::Rule->in(@ARGV);
См. Также здесь:
SO answer , предоставляющий CPAN
альтернативу File :: Find
.
ТАК вопрос об итераторах каталогов.
А вот и переписанное рекурсивное решение. На заметку: используйте strict
; использовать предупреждения
; и использование блока области видимости для создания статической переменной для подпрограммы.
use strict;
use warnings;
print $_, "\n" for dir_listing(@ARGV);
{
my @paths;
sub dir_listing {
my ($root) = @_;
$root .= '/' unless $root =~ /\/$/;
for my $f (glob "$root*"){
push @paths, $f;
dir_listing($f) if -d $f;
}
return @paths;
}
}
Вы всегда должны использовать строгие правила и предупреждения, чтобы облегчить отладку кода. Perl предупредил бы вас, например, о том, что @files
не объявлен. Но настоящая проблема с вашей функцией заключается в том, что вы объявляете лексическую переменную @paths
при каждом рекурсивном вызове list_dirs
и не возвращаете возвращаемое значение после шага рекурсии.
push @paths, list_dir($eachFile)
Если вы не хотите устанавливать дополнительные модули, возможно, вам поможет следующее решение:
use strict;
use warnings;
use File::Find qw(find);
sub list_dirs {
my @dirs = @_;
my @files;
find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
return @files;
}