Perl:如何在目录中搜索名为".cfg"的文件及其所有父目录

  • 本文关键字:文件 cfg Perl 搜索 perl
  • 更新时间 :
  • 英文 :


如何搜索名为".cfg"在一个目录及其所有父目录中我取的名字如下代码,但我想知道是否有更好的方法来做到这一点。我也想知道递归的方法来做同样的事情。

sub get_p4_config_updir($ $)
{
my ($client_root, $cfg_file) = @_;
# Dir from where search starts - it's a client root here
my $cur_dir = $client_root;
printf("**** cur_dir: $cur_dir ****n");
my $slashes = $cur_dir =~ y////;
printf("**** no of back slashes: $slashes ****n");
while($slashes > 2) {
my ($parent_dir, $b) = $cur_dir =~ /(.*)/(.*)/;
printf("**** parent_dir: $parent_dir, b: $b ****n");
$slashes--;
if (-e "$cur_dir/$cfg_file") {
printf("**** File exists in dir: $cur_dir ****n");
return $cur_dir;
}
$cur_dir = $parent_dir;
}
return "";
}
my $cfg = '.cfg';
my $dir = '/user/home/wkspace/abc/def/MAIN';
my $path = get_p4_config_updir($dir, $cfg);
if ($path ne "") {
printf("**** File exists in dir: $path ****n");
} else {
printf("**** File not found ****n");
}

Path::Tiny为例:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Path::Tiny;
# Returns a Path::Tiny object to the directory containing the file
# being looked for, or undef if not found.
sub get_p4_config_updir {
my ($client_root, $cfg_file) = @_;
my $dir = path($client_root)->realpath;
while (1) {
# say "Looking at $dir";
if ($dir->child($cfg_file)->exists) {
return $dir;
} elsif ($dir->is_rootdir) {
return undef;
} else {
$dir = $dir->parent;
}
}
}
my $cfg = '.cfg';
my $dir = '/user/home/wkspace/abc/def/MAIN';
say get_p4_config_updir($dir, $cfg) // "File not found";

或者类似于@rajashekar的想法,即通过使用chdir来获取每个目录的父目录来遍历目录树。这个使用File::chdir,它允许您local对当前工作目录的更改(并在函数/作用域退出时恢复原始目录),以及提供当前目录及其父目录的方便数组视图,可以进行操作:

use File::chdir;
...
sub get_p4_config_updir {
my ($client_root, $cfg_file) = @_;
local $CWD = $client_root; # Magic happens here
while (1) {
# say "Looking at $CWD";
if (-e $cfg_file) {
return $CWD;
} elsif ($CWD eq "/") {
return undef;
} else {
pop @CWD; # CDs to the next parent directory
}
}
}

您可以使用核心库以平台独立,可读的方式完成此操作,而不必使用cwd,并且可能在其余代码中导致远距离操作效果:

#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec::Functions qw(catfile rel2abs updir);
sub get_p4_config_updir
{
my ($dir, $file) = @_;
$dir = rel2abs($dir);
do {
my $path = catfile $dir => $file;
return $dir if -e $path;
return if $dir eq (my $new_dir = rel2abs(catfile $dir, updir));
$dir = $new_dir;
} while ('NOT_DONE');
return;
}
sub main {
my ($cfg, $dir) = @_;
my $path = get_p4_config_updir($dir, $cfg);
if (defined $path) {
printf("Found '%s' in '%s'n", $cfg, $path);
}
else {
printf(
"Did not find '%s' in '%s' or any of its parent directoriesn",
$cfg,
$dir,
);
}
}
main(@ARGV);

输出:

C:UsersuAppDataLocalTemp> perl p.pl linux.bin .
Found 'linux.bin' in 'C:'

当您可以使用..遍历目录结构时,为什么要处理路径名呢?

  • 如果当前目录中存在该文件,则返回该文件。
  • else上升..,重复此过程。
use Cwd qw(cwd);
sub search_up {
my ($dir, $file) = @_;
chdir($dir);
while (1) {
if (-e $file) {
print "$file exists in $dirn";
return $dir;
} elsif ($dir eq "/") {
return;
} else {
chdir("..");
$dir = cwd;
}
};
}

请看看以下代码片段符合您的要求。

脚本正在向文件系统的根目录查找配置文件,找到的文件名存储在数组@found中。

use strict;
use warnings;
use feature 'say';
my $dir = '/user/home/wkspace/abc/def/MAIN';
my $ext = 'cfg';
my($cwd,@found);
for( split('/',$dir) ) {
$cwd .= "$_/";
push @found, glob( $cwd . "*.$ext" );
}
if( @found ) {
say for @found;
} else {
say 'No file(s) was found';
}
exit 0;

下面的代码片段正在寻找从$dir开始的根文件系统之外的配置文件。

如果找到任何文件,那么它们将存储在数组引用$found下,然后在终端上打印出来。

如果没有找到任何文件,则会有消息通知您。

use strict;
use warnings;
use feature 'say';
my $dir = '/user/home/wkspace/abc/def/MAIN';
my $ext = 'cfg';
my $found = find($dir,$ext);
if( $found ) {
say for @$found;
} else {
say 'No file(s) was found';
}
exit 0;
sub find {
my $dir = shift;
my $ext = shift;
my $ret;

for( glob("$dir/*") ) {
push @$ret, $_ if /.$extz/;
if( -d ) {
my $found = find($_,$ext);
push @$ret, @$found if $found;  
}
}

return $ret;
}

最新更新