2009-05-18 7 views
1

私にはフォルダがあり、その中には多くのサブフォルダがあります。これらのサブフォルダには、多数の.htmlファイルが読み込まれています。私はそれを行うために次のコードを書いています。親フォルダと最初のサブフォルダが開き、1つの.htmlファイルしか印刷されません。それはエラーを示します:複数のディレクトリを読み込み、Perlのサブディレクトリの内容を読むにはどうすればよいですか?

NO SUCH FILE OR DIRECTORY 

私はコード全体を変更したくありません。既存のコードの変更は私には良いことです。

use FileHandle; 
opendir PAR_DIR,"D:\\PERL\\perl_programes\\parent_directory"; 
while (our $sub_folders = readdir(PAR_DIR)) 
{ 
     next if(-d $sub_folders); 

     opendir SUB_DIR,"D:\\PERL\\perl_programes\\parent_directory\\$sub_folders"; 
     while(our $file = readdir(SUB_DIR)) 
     { 

     next if($file !~ m/\.html/i); 
      print_file_names($file);  
     } 
     close(FUNC_MODEL1);  
} 
close(FUNC_MODEL); 

    sub print_file_names() 
    { 
    my $fh1 = FileHandle->new("D:\\PERL\\perl_programes\\parent_directory\\$file") 
       or die "ERROR: $!"; #ERROR HERE 
    print("$file\n"); 
    } 
+0

ヒント: "my"を "私たち"に使い、-wオプションを付けてperlを実行します(可能な場合は "use strict")。このエラーを早期に表示するのに役立ちました: "my"を使用しますが、厳密ではないと "$ file"は未定義であり、厳密に "$ file"は宣言されていないと警告するでしょう。 – araqnid

答えて

4

あなたはprint_file_names()機能で提供され$fileパラメータを抽出していません。

それは次のようになります。

sub print_file_names() 
{ 
    my $file = shift; 
    ... 
} 

外側のループであなたの-dテストはところで、あまりにも間違って見えます。あなたはnext if -d ...と言っています。これは、ディレクトリの内部ループをスキップすることを意味します。これは、必要とするものと完全に反対のようです。あなたがすべてのパス名ではなくパスに関連するファイル名だけである$fileをテストしているからです。また

注:

  1. PerlのWindows上では
  2. パス区切りとして/で細かい対処 を一度自分の親ディレクトリを設定し、その
  3. から他のパスを導き出す
  4. 代わりopendir(DIR, $path)
  5. の使用 opendir($scalar, $path)

nb:未テストコードは次のとおりです。

+0

ur素晴らしい....ありがとうalot dude ... – User1611

+1

File :: Find - a)を使用しないために私をdownvotedしたすべての人のために、私は彼にopendirなどを適切に使う方法を示していた、そしてb)彼は2つしか指定しなかったレベル2になっています。 – Alnitak

+0

- バグは実際にはopendirコードでもなく、print_file_names()にありました!! – Alnitak

1

210は、あなたが入れて起動してください

File::Find

3

を使用して検討している:

use strict; 
use warnings; 

すべてのスクリプトの先頭に、それはあなたがこのような問題を回避し、多くのあなたのコードを行いますより読みやすい。

あなたはここでそれについての詳細を読むことができます:Perlmonks

6

あなたの投稿コードが邪魔overcomplicated見えます。 File::Find::Ruleをチェックしてください。ほとんどのコードを少しずつ書き上げることができます。

use File::Find::Rule; 

my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->start("D:/PERL/perl_programes/parent_directory"); 

while(my $file = $finder->match() ){ 
    print "$file\n"; 
} 

つまり、はセクシーではありませんか?

ユーザーは、Depth = 2のエントリのみを使用したいと考えているとコメントしました。

use File::Find::Rule; 

my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->mindepth(2)->maxdepth(2)->start("D:/PERL/perl_programes/parent_directory"); 

while(my $file = $finder->match() ){ 
    print "$file\n"; 
} 

この制限が適用されます。

+1

name( "* .html")は正規表現が行ったのと同じファイルとは一致しません。幸いにも、name()はglobsと同様に正規表現を受け入れます。私は一致する条件を修正しました。 – cjm

+0

これは彼の要求に反して、木のレベル1と3+にファイルが存在するはずです。 – Alnitak

+0

@Alnitak:検索のためのマインド・フェースとマックス・ディープを設定するのは簡単です。 –

3

あなたはそれを強固にするために全体のコードを変更する必要があるとしている。

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::Find; 

my $top = $ENV{TEMP}; 

find({ wanted => \&wanted, no_chdir=> 1 }, $top); 

sub wanted { 
    return unless -f and /\.html$/i; 
    print $_, "\n"; 
} 

__END__ 
0

ここでファイルを使用することを必要としないものの方法::検索です:

まず、ルートディレクトリを開き、 readdirを使用してすべてのサブフォルダの名前を配列に格納します。

次に、foreachループを使用します。各サブフォルダに対して、ルートディレクトリとフォルダの名前をリンクして新しいディレクトリを開きます。 readdirを使用してファイル名を配列に格納します。

最後の手順は、このforeachループの内部でファイルを処理するためのコードを記述することです。

私にこのアイデアを与えてくれた先生に感謝します:)本当にうまくいきました!

関連する問題