打印给定目录的文件和子目录
Print files and subdirectories of given directory
我正在尝试从给定目录中获取所有文件和目录,但无法指定类型(文件/目录)。没有任何内容正在打印。我做错了什么以及如何解决它。这是代码:
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);
}
使用此 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 =~ /.*\/(.*)/ && =~ /\./){
#push @fileList, $File::Find::name."\n";
}
readdir
returns只有节点名,没有任何路径信息。如果没有指定路径,文件测试操作符将在当前工作目录中查找,并且因为当前目录不是 $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 $!;
}
已回答,但有时不关心实现细节很方便,您可以使用一些 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
文件,等等......这样的 "files" 通常可以作为普通文件打开和读取,因此 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 真的值得安装。
我正在尝试从给定目录中获取所有文件和目录,但无法指定类型(文件/目录)。没有任何内容正在打印。我做错了什么以及如何解决它。这是代码:
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);
}
使用此 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 =~ /.*\/(.*)/ && =~ /\./){
#push @fileList, $File::Find::name."\n";
}
readdir
returns只有节点名,没有任何路径信息。如果没有指定路径,文件测试操作符将在当前工作目录中查找,并且因为当前目录不是 $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 $!;
}
已回答,但有时不关心实现细节很方便,您可以使用一些 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
文件,等等......这样的 "files" 通常可以作为普通文件打开和读取,因此 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 真的值得安装。