- ベストアンサー
ファイルの中身に対する再帰的検索
初心者です。 テキストファイルの中身を調べて、その中に特定の拡張子を持ったファイル名があれば更にその中身を調べていって、階層構造になったファイルを全て調べあげるスクリプトを作ろうとしています。 例えばfile1.txtの中身が ... hoge file2.txt file3.txt hogehoge ... だったとすれば、今度はfile2.txtおよびfile3.txtの中身に.txtという拡張子を持ったファイル名があるかどうか調べ、該当するものが無くなるまで調べていきます。 これらのテキストファイルは全て同じディレクトリ内に存在します。 どういう具合のループにすればよいのか想像がつきません。 アドバイスお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは ループを二重にしてみました $dir = "c:\\temp"; $ext = "txt"; $start = "file1.txt"; @buf1 = ($start); while (@buf1) { @buf2 = (); foreach $file (@buf1) { next if (++$cunt{lc($file)} > 1); open(F, "<$dir\\$file") || next; print STDERR "$file Open!!\n"; while (<F>) { if (($newfile) = lc =~ /^\s*(.+\.$ext)\s*$/) { push(@buf2, $newfile); } } close(F); } @buf1 = @buf2; }
その他の回答 (2)
- Tacosan
- ベストアンサー率23% (3656/15482)
「新しいファイル」に対する処理をいつ行うのかにもよりますが, 「現在のファイルを処理してから」ということであれば my @files = ('file1.txt'); my %read; while (@files) { my $file = shift @files; next unless $read{$file}++; open(my $fh, $file); while (my $line = <$fh>) { (chomp($line), push @files, $line and next) if $line =~ /\.txt$/; $line に対して何か処理 } close($fh); } のような感じでできるかもしれません. 「新しいファイルを見付けたらすぐ処理する」方針だと再帰ですね. ちなみに動作チェックはしてません.
お礼
ご回答ありがとうございます。 ファイルを処理するタイミングはいつでもよいので、ご回答いただいたやり方で全く問題ないです。 参考になります。
- rafysta
- ベストアンサー率45% (24/53)
こんな感じでサブルーチンの再帰呼び出しをしてみたらどうでしょうか?(動作チェックしてないです。) 1つ問題となるのは、例えば、file2.txtにfile3.txtと書いてあって、file3.txtにfile2.txtと描いてあった場合に、無限ループに陥るので何らかの対策が必要です。(下のサンプルでは、ハッシュを使ってチェックすることにしてみました。) my %duplicate; &read("file1.txt"); sub read{ my @files = @_; if(@files == 0){ return; } # 新しいファイルを開いて次のターゲットを探す my @nextFiles; foreach my $file(@files){ open IN, $file or die "cannot open $file: $!"; while(<IN>){ if(m/\.txt$/){ unless(exists $duplicate{$_}){ push @nextFiles, $_; $duplicate{$_} = 1; } } } close IN; } # 再帰呼び出し &read(@nextFiles); }
お礼
おっしゃるとおり、無限ループになる可能性がありますね。 質問投稿時には気がつきませんでした。 ご指摘、そしてご回答まことにありがとうございます。
お礼
ありがとうございます。配列にファイル名をどんどん追加していくわけですね。 案外単純な具合にできるものなんですね。非常に勉強になりました。