2013-05-22 51 views
1

我有一個Perl腳本來計算表達式在文件中出現的次數,在這種情況下,它計算'<'和'>'之間發現的所有內容,因爲我希望它解析.xml文件。Perl中的遞歸打開文件

SCRIPT:

#usr/bin/perl 

sub by_count { 
    $count{$b} <=> $count{$a}; 
} 

open(INPUT, "<[Content_Types].xml"); 
open(OUTPUT, ">output"); 
$bucket = qw/./; 


while(<INPUT>){ 
    @words = split(/\</); 

    foreach $word (@words){ 
      if($word=~/($bucket*>)/io){ 

     #print OUTPUT "$word"; 
     #print OUTPUT "\n\n"; 
     $count{$1}++;} 

    } 
} 
foreach $word (sort by_count keys %count) { 

    print OUTPUT "<$word occurs $count{$word} times\n\n"; 

} 

close INPUT; 
close OUTPUT; 

輸出

<Default Extension="xlsx" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"/> occurs 1 times 

<Default Extension="png" ContentType="image/png"/> occurs 1 times 

<Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/> occurs 1 times 

問題

我想遞歸地做到這一點。我有一個包含多個子目錄的目錄,每個子文件夾內都有一個[Content_Types] .xml文件。任何有關如何解析主目錄中找到的具有該名稱的文件的建議?

示例圖:

>Directory 
    >Directory1 
    >[Content_Types].xml 
    >Directory2 
    >[Content_Types].xml 
    >Directory3 
    >[Content_Types].xml 
    . 
    . 
    . 

    >Directory100 
    >[Content_Types].xml 

回答

4

一種方法是使用模塊Find::File,該模塊將遍歷所有子目錄以找到您所告訴的內容。這將是這樣的:

#!/usr/bin/env perl 

use warnings; 
use strict; 
use File::Find; 

find(\&wanted, shift); 

sub wanted { 
     return unless -f $_ && m/\[Content_Types\]\.xml/; 
     open my $fh, '<', $_ or do { 
       warn qq|WARNING: Could not open $File::Find::name\n|; 
       return; 
     }; 
     open my $ofh, '>', 'output'; 
     my $bucket = qw/./; 

     while (<$fh>) { 
       ## ... your code here ... 
     } 

     ## ... your code here ... 
} 

給作爲參數,你希望搜索開始的目錄:

perl script.pl . 
+1

+ 1不使用'File :: Find'重新發明輪子 – Prix

+0

我應該在哪些代碼中放置## ...您的代碼在這裏......? –

+0

@BrunoAlexandre:'wanted'函數與腳本幾乎相同,但是每個xml文件都執行一次。 'while(<$fh>){...}'就像你的'while',之後你執行'foreach'。這裏也一樣。此外,我還爲'open'函數使用詞法範圍變量。我認爲這是更好的編碼和更安全。 – Birei

2

這不是真的有必要遞歸地做到這一點。它迭代運行非常好。

定義目錄的堆棧:

my @directories; 

然後按下啓動目錄到列表:

push(@directories, "startdirectory"); 

最後,作爲一個循環,你可以這樣做:

while(my $dir=shift(@directories)) 

然後,對於每個遍歷的目錄,將所有找到的子目錄推送到列表中。之後,根據需要查找文件並解析它們(即添加上面列出的代碼)。

提示:您可以檢查是否有(-d myfile)的目錄。

+0

我發現了一個錯誤。你能否將這些行添加到我的代碼中,並將它放在這裏完成? –