给定目录的打印文件和子目录
我想从给定目录中获取所有文件和目录,但我无法指定什么类型(文件/目录)。没有什么正在打印。我做错了什么以及如何解决它。以下是代码:给定目录的打印文件和子目录
sub DoSearch {
my $currNode = shift;
my $currentDir = opendir (my $dirHandler, $currNode->rootDirectory) or die $!;
while (my $node = readdir($dirHandler)) {
if ($node eq '.' or $node eq '..') {
next;
}
print "File: " . $node . "\n" if -f $node;
print "Directory " . $node . "\n" if -d $node;
}
closedir($dirHandler);
}
readdir
仅返回没有任何路径信息的节点名称。该文件的测试运营商将看在当前工作目录,如果没有指定路径,因为当前目录是不是$currNode->rootDirectory
他们不会被人发现
我建议你使用rel2abs
从File::Spec::Functions
核心模块的节点相结合名称与路径。您可以使用字符串连接,但库函数处理角落情况,如目录是否以斜线结尾
还值得指出的是,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 $!;
}
恢复原来的工作目录
使用此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";
}
已经回答了,但有时候不太在意实施细节,您可以使用一些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
文件,等等......这样的“文件”通常可以作为普通文件打开和阅读,因此,某些事件而不是-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真的值得安装。
谢谢您给出的解决方案。第一个解决了我的问题:) –