WEB相談室

Webページ作成に関しての何でも掲示板です。

タイトル:File::Findで全ファイルに処理

0:[投稿] あやの [2002/07/15 16:29 ][環境:UNIX系+IE UNIX系+Perl]

File::Findを使用して、任意のディレクトリ配下にある全ファイルに対して、処理を行いたいと思っています。
以下のようなプログラムを組みました。
-------------------------------------------------
package AAA;
use File::Find;

sub find_file{
    my ($self,$dir) = @_;

    use vars qw/*name/;
    *name = *File::Find::name;

    my @filelist;

    find(\&wanted,$dir);
    return @filelist;

    sub wanted{
        push @filelist,$name if /\.(htm|html)$/si;
    }
}

package main;

my @dir = ('/hoge/','/foo/');
foreach $d (@dir){
    my @file = $AAA->file_find;
    foreach $a (@file){
        処理・・
    }
}
-------------------------------------------------
これを実行したところ、/hoge/配下のファイルは処理されたのですが、次の/foo/配下のファイルは処理がされませんでした。
調べたところ、/foo/の場合は@filelistに値が入っていないようです。
それがなぜだかが分かりません。
それと、実行時に
Variable "@filelist" will not stay shared at line 16.
というエラーも出ています。これは何なのでしょう?
よろしくお願いします。


1:[回答] 下級天使 [2002/07/15 16:58 ]

>Variable "@filelist" will not stay shared at line 16.
>というエラーも出ています。これは何なのでしょう?

my変数のスコープの問題です。
@filelistは、sub "find_file"で宣言されており、
それを sub "wanted"内で、使用しています。

my→localにしたら、エラーがとれると思いますが。


2:[質問] あやの [2002/07/15 17:29 ]

回答ありがとうございます。

>my→localにしたら、エラーがとれると思いますが。
確かに 「Variable "@filelist" will not stay shared at line 16.」というエラーは取れました。
しかし、新たに「Global symbol "@filelist" requires explicit package name at line 16.」というエラーが出てきてしまいました。
@filelistはどこでどのように宣言すればいいのでしょう?
いろいろ試しているのですが・・


3:[回答] AA [2002/07/16 09:18 ]

file_find と find_file があったり、
$AAA が package AAA と無関係だったり、
$d が渡っていなかったり、
>>0 のスクリプトはちゃんと動かないと思いますが。

my @filelist は2回呼ばれるけど、sub wanted は1度しかコンパイルされないので、
sub wanted の中の @filelist がうまく作れないのが原因のようです。
なので、以下のようにすると直ります。

package AAA;
use strict;
use File::Find;

sub new { bless {}, shift; }

sub find_file {
   my ($self, $dir) = @_;

   eval q{
       my @filelist;
       find(\&wanted, $dir);
       return @filelist;
       sub wanted {
           push @filelist, $File::Find::name if /\.html?$/si;
       }
   };
}

package main;
use strict;

my $AAA = new AAA;
my @dir = qw{/hoge /foo};
foreach my $d (@dir) {
   my @file = $AAA->find_file($d);
   foreach my $a (@file) {
       print "$a\n";
   }
}


4:[完了] あやの [2002/07/16 14:44 ]

AAさん、回答ありがとうございます。

>file_find と find_file があったり、
>$AAA が package AAA と無関係だったり、
>$d が渡っていなかったり、
>>>0 のスクリプトはちゃんと動かないと思いますが。
すいませんでした。分かりづらいプログラム例を表記してしまいました。
今後注意します。

問題は修正していただいたスクリプトで解決しました^^
evalのことを勉強して出直したいと思います。
お二方共、本当にありがとうございました。


5:[完了] ふじ [URL] [2002/07/16 22:11 ]

無名サブルーチンへのリファレンスを使って、

sub find_file {                                                                                
   my ($self, $dir) = @_;                                                                      
                                                                                               
   my @filelist;                                                                              
   find(                                                                                      
       sub {                                                                                  
           push @filelist, $File::Find::name if /\.html?$/si;                                  
       },                                                                                      
       $dir                                                                                    
   );                                                                                          
                                                                                               
   return @filelist;                                                                          
}

こんな感じでどうでしょ?

# ベンチマーク取ったけど、eval を使うのと比べてパフォーマンスに差は出ませんでした。

回答(必須): 状態:

お名前(必須):

e-mail:

URL:




[戻る]

ChaichanPAPA's World