我写了一些脚本,递归打印目录的内容。但它会为每个文件夹打印警告。如何解决这个问题?
示例文件夹:
dev#cd / tmp / test
dev#ls -p -R
test2 /
testfile
testfile2
./ TEST2:
testfile3
testfile4
我的代码:
#!/usr/bin/perl
use strict;
use warnings;
browseDir('/tmp/test');
sub browseDir {
my $path = shift;
opendir(my $dir, $path);
while (readdir($dir)) {
next if /^\.{1,2}$/;
if (-d "$path/$_") {
browseDir("$path/$_");
}
print "$path/$_\n";
}
closedir($dir);
}
和输出:
dev #perl /tmp/cotest.pl
/ tmp / test / test2 / testfile3
/ tmp / test / test2 / testfile4
使用未初始化的值$ _ in 连接(。)或字符串在/tmp/cotest.pl第16行。
/ tmp / test /
的/ tmp /测试/ testfile的
/ TMP /测试/ testfile2
答案 0 :(得分:1)
您可以试试这段代码:
#!/usr/bin/perl
use strict;
use warnings;
browseDir('/tmp');
sub browseDir {
my $path = shift;
opendir(my $dir, $path);
while (readdir($dir)) {
next if /^\.{1,2}$/;
print "$path/$_\n";
if (-d "$path/$_") {
browseDir("$path/$_");
}
}
closedir($dir);
}
如果你收到了这个错误,那是因为你在使用变量$ _。
之前调用browseDir()答案 1 :(得分:1)
您在调用$_
之前在browseDir
中放置了一个值,并且您希望在调用browseDir
(合理预期)后显示该值,但browseDir
会修改该值变量
只需将local $_;
添加到browseDir
,以确保在子退出之前撤消对其的任何更改。
与您的问题无关,此处还有其他三个问题:
".\n"
和"..\n"
。修正:
#!/usr/bin/perl
use strict;
use warnings;
browseDir('/tmp/test');
sub browseDir {
my $path = shift;
opendir(my $dh, $path) or die $!;
my @files = readdir($dh);
closedir($dh);
for (@files) {
next if /^\.{1,2}z/;
if (-d "$path/$_") {
browseDir("$path/$_");
}
print "$path/$_\n";
}
}
最后,为什么不使用像File::Find::Rule这样的模块?
use File::Find::Rule qw( );
print "$_\n" for File::Find::Rule->in('/tmp');
注意:在5.12之前,while (readir($dh))
必须写为while (defined($_ = readdir($dh)))
答案 2 :(得分:1)
为什么不使用File::Find模块?自Perl 5.x以来,它几乎包含在Perl的所有发行版中。这不是我最喜欢的模块,因为它的工作方式很混乱,但它做得很好。
您可以定义一个wanted
子例程来执行您想要的操作并过滤掉您不想要的内容。在这种情况下,您几乎打印了所有内容,因此所有wanted
都会打印出找到的内容。
在File::Find
中,文件名保存在$File::Find::name
中,该文件的目录位于$File::Find::dir
。 $_
是文件本身,可用于测试。
以下是您想要的基本方式:
use strict;
use warnings;
use feature qw(say);
use File::Find;
my $directory = `/tmp/test`;
find ( \&wanted, $directory );
sub wanted {
say $File::Find::Name;
}
我更喜欢将wanted
函数放在我的find
子例程中,因此它们在一起。这相当于上面的内容:
use strict;
use warnings;
use feature qw(say);
use File::Find;
my $directory = `/tmp/test`;
find (
sub {
say $File::Find::Name
},
$directory,
);
良好的编程说不要在子程序中打印。相反,您应该使用子例程来存储和返回数据。不幸的是,find
根本没有返回任何内容。您必须使用全局数组来捕获文件列表,然后将其打印出来:
use strict;
use warnings;
use feature qw(say);
use File::Find;
my $directory = `/tmp/test`;
my @directory_list;
find (
sub {
push @directory_list, $File::Find::Name
}, $directory );
for my $file (@directory_list) {
say $file;
}
或者,如果您更喜欢单独的wanted
子例程:
use strict;
use warnings;
use feature qw(say);
use File::Find;
my $directory = `/tmp/test`;
my @directory_list;
find ( \&wanted, $directory );
sub wanted {
push @directory_list, $File::Find::Name;
}
for my $file (@directory_list) {
say $file;
}
我想要的子程序取决于一个不在子程序本地的数组这个事实困扰我,这就是为什么我更喜欢在我的wanted
调用中嵌入find
子程序。
您可以做的一件事是使用您的子程序过滤掉您想要的内容。假设您只对JPG文件感兴趣:
use strict;
use warnings;
use feature qw(say);
use File::Find;
my $directory = `/tmp/test`;
my @directory_list;
find ( \&wanted, $directory );
sub wanted {
next unless /\.jpg$/i; #Skip everything that doesn't have .jpg suffix
push @directory_list, $File::Find::Name;
}
for my $file (@directory_list) {
say $file;
}
注意想要的子例程在我将其推入next
数组之前对我不想要的任何文件执行@directory_list
的过程。再次,我更喜欢嵌入:
find (sub {
next unless /\.jpg$/i; #Skip everything that doesn't have .jpg suffix
push @directory_list, $File::Find::Name;
}
我知道这不完全是您的要求,但我只是想让您了解Find::File
模块,并向您介绍可以添加的Perl模块(如果您还不知道它们) Perl的许多功能。