无法从$ File :: Find :: name - perl获取文件的绝对路径

问题描述:

我无法从$ File :: Find :: name获取文件的绝对路径。它显示undef谷值作为输出。无法弄清楚,为什么:(任何一个可以请帮我在显示此

错误是:使用未初始化值$ FILE_NAME的级联

我的代码:

use strict; 
use warnings; 
use File::Find; 
use File::Path qw(make_path); 
use File::Copy; 
use Cwd; 
use Data::Printer; 

my $rootPATH = $ARGV[0]; 
my $id  = $ARGV[1]; 
my @Arraypath; 
my $file_name; 
our $anr_name; 

opendir(my $DIR, $rootPATH); 
while (my $entry = readdir $DIR) { 
    next unless -d $rootPATH . '/' . $entry; 
    next if $entry eq '.' or $entry eq '..'; 
    #print "Found directory $entry\n"; 
    push(@Arraypath, (split("\n", $entry))); 
} 
closedir $DIR; 
my $count = 0; 
foreach my $line (@Arraypath) { 
    my $fulllogpath = $rootPATH . "\\" . $line; 
    #print "$fulllogpath\n"; 
    $count++; 

    start($fulllogpath); 
} 

sub start { 
    my $fulllogpath = shift; 
    our @content; 
    #print "$fulllogpath\n\n"; 

    find(\&wanted, $fulllogpath); 

    sub wanted { 
     push @content, $_; 
     return; 
    } 

    foreach my $file (@content) { 
     # print "$file\n\n"; 
     if ($file =~ /traces[_d]*/) { 
      print "$file\n\n"; 
      $file_name = $File::Find::name; 
      p $file_name; 
      print "$file_name\n"; 
     } 
    } 
} 
+1

'$文件::查找:: name'才有效在'wanted'函数中。不在其外面。 – dgw 2014-09-02 11:18:18

+0

是否有任何其他方式来获取文件的绝对路径? – user1362796 2014-09-02 11:20:13

+1

您可以在'wanted'子文件中存储完整路径。将'$ _'更改为'$ File :: Find :: name'。虽然可能有更适合这个工作的模块。 – TLP 2014-09-02 12:32:26

你的程序布局非常糟糕,如果你正确缩进并使用仔细选择的标识符,编写和调试代码会简单得多:对于一个子程序来说,start这样的名字是没有用处的。

您也有不必要的子程序声明,它会分解程序流程并使其不便遵循。

为什么你有几个包变量(用our声明)?通常不需要它们,最好在整个地方使用词法变量,在适当的地方声明,以便所有代码在需要时都可以访问它们。

最好使用File::Spec来处理文件路径,而不是使用字符串运算符来处理它们,这很容易犯错。

管理find结果的最佳方式是使用绝对路径。它看起来像你想要做的不仅仅是打印find返回的结果,因为你加载了像CwdFile::Copy这样的模块,但是不知道其他目的是什么,我不能帮你编写它。

该代码删除所有的子程序,并使一切更简洁。

use strict; 
use warnings; 
use autodie; 

use File::Find 'find'; 
use File::Spec; 
use Data::Printer; 

my ($root_path, $id) = @ARGV; 

opendir my ($dh), $root_path; 
my @dir_list = 
    grep -d, 
    map File::Spec->catfile($root_path, $_), 
    grep { not /\A\.\.?\z/ } readdir $dh; 
closedir $dh; 

my $count; 

for my $dir (@dir_list) { 

    ++$count; 

    find(sub { 

     return unless /traces[_d]*/; 

     my $file = $_; 
     print "$file\n\n"; 

     my $file_name = $File::Find::name; 
     p $file_name; 
     print "$file_name\n"; 

    }, $dir); 
} 

正如已经指出,$File::Find::name只在wanted功能有效。不在其外面。

不过,我会建议作出转变以跨平台兼容的方式使用Path::ClassPath::Class::Rule为您的文件的一些简单的处理:

use strict; 
use warnings; 

use Data::Printer; 
use Path::Class; 
use Path::Class::Rule; 

my ($root_path, $id) = @ARGV; 

my $dir = dir($root_path); 

my $next = Path::Class::Rule->new->file->name(qr{traces[_d]*})->iter(
    grep { $_->is_dir() } $dir->children 
); 

while (my $file = $next->()) { 
    # Accomplishes the same as your script. I suspect these prints statements are mostly for debugging though. 
    print $file->basename(), "\n\n"; 
    p "$file"; 
    print "$file\n"; 
}