2012-02-27 24 views
3

私は、スクリプトが置かれているフォルダから始まるファイル構造を表示するスクリプトを作成しようとしています。スクリプトは再帰呼び出しなしでうまく動作しますが、その呼び出しによって、次のメッセージでクラッシュします。closedir()は、printFiles.pl行24の無効なdirhandle DIRで試みました。フォルダが印刷され、実行が最後の行に達しましたが、再帰呼び出しが行われないのはなぜですか?そして、私は代わりにこれを解決すべきですか?あなたのPerlプログラムの開始時にPerlの再帰的なディレクトリトラバーサル

#!/usr/bin/perl -w 

printDir("."); 
sub printDir{ 
opendir(DIR, $_[0]); 
local(@files); 
local(@dirs); 
(@files) = readdir(DIR); 
foreach $file (@files) { 
    if (-f $file) { 
     print $file . "\n"; 
    } 
    if (-d $file && $file ne "." && $file ne "..") { 
     push(@dirs, $file); 
    } 
} 
foreach $dir (@dirs) { 
    print "\n"; 
    print $dir . "\n"; 
    printDir($dir); 
} 
closedir(DIR); 
} 
+1

'ls -R'についてはどうですか? – TLP

+0

私は知っているが、それは簡単な方法を行うには面白くない。 – nist

答えて

7
  • あなたはする必要があり、常にuse strict;use warnings;、あなたはそれで助けを求める前に、特に。そうすれば、Perlは多くの直接的なエラーを表示します。 DIRがグローバルディレクトリハンドルで、サブルーチンの前回の実行により、既に閉鎖されているため

  • 無効なファイルハンドルエラーがありそうです。それは、常にファイルやディレクトリの両方のための字句のハンドルを使用するのがベストです、そして必ずオープンが成功するためにリターンコードをテストするために、この

    opendir my $dh, $_[0] or die "Failed to open $_[0]: $!"; 
    

    のような字句ファイルハンドルの一つの利点は、ときに彼らが暗黙的に閉じられていることです範囲外になるので、サブルーチンの最後にclosedirコールを行う必要はありません。

  • localは、そのように使用するつもりはありません。宣言としては十分ではなく、すべてがアクセスできるグローバル変数の一時的なコピーを作成しています。また、この

    my @dirs; 
    my @files = readdir $dh; 
    
  • のように、あなたはreaddirから使用しているファイル名にパスを持っていない、とあなたがディレクトリにchdirを処理されているか、ディレクトリを追加するいずれかのない限り、あなたのファイルのテストが失敗し、代わりにmyを使用するのが最善パス文字列をテストする前にファイル名に置き換えてください。

+0

これは多くの回答をいただきありがとうございます – nist

3

File::Findモジュールを使用してください。私が通常これを行う方法は、と同じパラメータをとり、を見つけ、File :: Findを使って適切なperlスクリプトを作成する、perlに付属のfind2perlツールを使用しています。それから私はそれが欲しいことをするために生成されたスクリプトを微調整します。しかし、File :: Findを直接使うこともできます。

3

なぜわからないuse File::Find

use strict; #ALWAYS! 
use warnings; #ALWAYS! 
use File::Find; 

find(sub{print "$_\n";},".");