2016-09-19 11 views
1

私は、指定されたディレクトリの下のすべてのディレクトリを再帰的に検索する関数を作成しようとしています。Perlによる再帰に失敗しました

use strict; 
use warnings; 



sub printDir 
{ 
     my $root = shift; 

     opendir DIR, $root or die "can't open dir $root\n"; 
     my $dir; 
     while ($dir = readdir DIR) 
     { 

       if (-d "$root/$dir" && "$dir" ne '.' && "$dir" ne '..') 
       { 
         print "$dir\n"; 
         &printDir ("$root/$dir"); 
       } 
     } 

} 


my $root = $ARGV[0]; 
printDir $root; 

ディレクトリ階層は次のようである場合:

A 
/\ 
B C 
| 
D 

コードが検索されない-B-DおよびCを検索した後に停止します。コードの何が間違っていますか?

ありがとうございます。

+3

アンパサンドとカッコで1回、これらのどちらでも1回も使用しないと、なぜprintDirを呼び出しますか?アンパサンドを使用することは決して必要ではなく、あなたが望まないいくつかの副作用を持つ可能性があります。括弧を使い、アンパサンドを忘れてください。 –

答えて

8

あなたのディレクトリハンドルはグローバルです。

opendir DIR, $root or die "can't open dir $root\n"; 

サブを呼び出すたびに上書きされます。 1回の呼び出しが完了して最後のスコープに戻ると、DIRは、最後にすでに読み込まれた最後のディレクトリを指しているので、他のものを読み取ることはなく、最も内側のディレクトリが読み込みを終了するとすぐに完全に停止します。

代わりにレキシカルディレクトリハンドルを使用する必要があります。

opendir my $dh, $root or die "can't open dir $root\n"; 
while (my $dir = readdir $dh) 
{ 
    ... 
} 

at readdir in perldocも参照してください。

6

問題は、次の行にあります。

opendir DIR, $root or die "can't open dir $root\n"; 

あなたはすべての再帰呼び出しによって作成されたすべてのディレクトリハンドルのために同じ記号(すなわちDIR)を使用しています。各呼び出しが独自のディレクトリハンドルを取得するようにする必要があります。だから、あなたが上記の行を変更します。そして、あなたはまた、一般的には

while ($dir = readdir $dirh) 

while試験条件を調整する必要があり

opendir my $dirh, $root or die "can't open dir $root\n"; 

、現代perlでは、常に(ファイル/ディレクトリハンドルのためのレキシカル変数を使用する必要があります例えばopen my $handle,'<','somefile')。

関連する問題