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

时间:2014-09-02 11:06:46

标签: perl

我无法从$ File :: Find :: name获取文件的绝对路径。它显示了作为输出的undefale。无法弄清楚原因:(任何人都可以帮我解决这个问题

显示错误:在连接中使用未初始化的值$ 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";
        }
    }
}

2 个答案:

答案 0 :(得分:2)

你的节目布局很差。如果正确缩进并使用精心选择的标识符,编写和调试代码会更简单:子例程的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);
}

答案 1 :(得分:0)

如前所述,$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";
}