2014-09-02 68 views
0

我無法從$ 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

回答

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); 
} 
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"; 
}