我正在尝试从给定目录中获取所有文件和目录,但我无法指定类型(文件/目录)。什么都没打印出来。我做错了什么以及如何解决它。这是代码:
rows
答案 0 :(得分:5)
readdir
仅返回没有任何路径信息的节点名称。如果没有指定路径,文件测试操作员将查看当前工作目录,并且因为当前目录不是$currNode->rootDirectory
,所以不会找到它们
我建议您使用File::Spec::Functions
核心模块中的rel2abs
将节点名称与路径相结合。您可以使用字符串连接,但库函数会处理极端情况,例如目录是否以斜杠结尾
值得指出的是,Perl标识符通常位于snake_case
,熟悉该语言的人会感谢您不使用大写字母。对于标识符的第一个字符,尤其应该避免使用它们,因为这样的名称是为包名称
我认为你的子程序看起来应该是这样的
use File::Spec::Functions 'rel2abs';
sub do_search {
my ($curr_node) = @_;
my $dir = $curr_node->rootDirectory;
opendir my $dh, $dir or die qq{Unable to open directory "$dir": $!};
while ( my $node = readdir $dh ) {
next if $node eq '.' or $node eq '..';
my $fullname = rel2abs($node, $dir);
print "File: $node\n" if -f $fullname;
print "Directory $node\n" if -d $fullname;
}
}
另一种方法是将当前工作目录设置为正在读取的目录。这样就不需要操作文件路径,但是你需要在更改之前和之后保存和恢复原始工作目录
Cwd
核心模块提供getcwd
,您的代码看起来像这样
use Cwd 'getcwd';
sub do_search {
my ($curr_node) = @_;
my $cwd = getcwd;
chdir $curr_node->rootDirectory or die $!;
opendir my $dh, '.' or die $!;
while ( my $node = readdir $dh ) {
next if $node eq '.' or $node eq '..';
print "File: \n" if -f $node;
print "Directory $node\n" if -d $node;
}
chdir $cwd or die $!;
}
答案 1 :(得分:1)
使用此CPAN模块递归获取所有文件和子目录。
use File::Find;
find(\&getFile, $dir);
my @fileList;
sub getFile{
print $File::Find::name."\n";
# Below lines will print only file name.
#if ($File::Find::name =~ /.*\/(.*)/ && $1 =~ /\./){
#push @fileList, $File::Find::name."\n";
}
答案 2 :(得分:1)
已经回答了,但有时候很方便不关心实现细节,你可以使用一些CPAN模块来隐藏这些细节。
其中一个是精彩的Path::Tiny模块。
您的代码可以是:
use 5.014; #strict + feature 'say' + ...
use warnings;
use Path::Tiny;
do_search($_) for @ARGV;
sub do_search {
my $curr_node = path(shift);
for my $node ($curr_node->children) {
say "Directory : $node" if -d $node;
say "Plain File : $node" if -f $node;
}
}
children
方法会自动排除.
和..
。
您还需要了解-f
测试仅适用于真实的files
。因此,上面的代码排除了例如symlinks
(其指向真实文件)或FIFO
文件等等......这样的“文件”通常可以打开并作为普通文件读取,因此somethimes代替-f
可以方便地使用-e && ! -d
测试(例如存在,但不是目录)。
Path::Tiny
有一些方法,例如你可以写
for my $node ($curr_node->children) {
print "Directory : $node\n" if $node->is_dir;
print "File : $node\n" if $node->is_file;
}
is_file
方法通常是DWIM - 例如做:-e && ! -d
。
使用Path::Tiny
您还可以使用iterator
方法轻松扩展您的函数以遍历整个树:
use 5.014;
use warnings;
use Path::Tiny;
do_search($_) for @ARGV;
sub do_search {
#maybe you need some error-checking here for the existence of the argument or like...
my $iterator = path(shift)->iterator({recurse => 1});
while( my $node = $iterator->() ) {
say "Directory : ", $node->absolute if $node->is_dir;
say "File : ", $node->absolute if $node->is_file;
}
}
上面打印了从给定参数递归下来的所有文件和目录的类型......
等等...... Path::Tiny真的值得安装。