ファイルの検索1
■この章で解説するモジュール
File::Find (find, finddepth)
■この章でできること
・ファイルやディレクトリを再帰的に検索する

 File::Findモジュールを使うと、ファイルやディレクトリを再帰的に検索することができます。では、まずは簡単なサンプルから見てみましょう。

#!/usr/bin/perl

#############################################
# ファイルの検索のサンプル1
# Author: "Perl Programming Tips"
#############################################

use File::Find;

# ファイルを検索する
print "find test 1 **********************\n";
find(\&want_func, ".");
print "\n";

# 複数ディレクトリからファイルを検索する
print "find test 2 **********************\n";
find(\&want_func, ("temp1", "temp2"));
print "\n";

# オプションを指定してファイルを検索する
# finddepth(\&want_func, "."); と同等
print "find test 3 **********************\n";
find({wanted => \&want_func, bydepth => 1}, ".");

# ファイル検索用サブルーチン
sub want_func
{
    print "$File::Find::name\n";
}

 実行結果は次のようになります。

[g@630m temp]$ perl file10_01.pl 
find test 1 **********************
.
./file10_01.pl
./temp1
./temp1/file1.txt
./temp1/file2.txt
./temp2
./temp2/file3.txt
./temp2/subdir1
./temp2/subdir1/file4.txt

find test 2 **********************
temp1
temp1/file1.txt
temp1/file2.txt
temp2
temp2/file3.txt
temp2/subdir1
temp2/subdir1/file4.txt

find test 3 **********************
./file10_01.pl
./temp1/file1.txt
./temp1/file2.txt
./temp1
./temp2/file3.txt
./temp2/subdir1/file4.txt
./temp2/subdir1
./temp2
.
[g@630m temp]$

 ファイルを検索するには、File::Find::find関数を使います。

File::Find::find
指定したディレクトリ内のファイルやディレクトリを再帰的に検索する。
書式
find \&wanted, @directories
find \%options, @directories
引数
wanted:
サブルーチンへのリファレンス
options:
wantedサブルーチンやオプションを指定したハッシュへのリファレンス
directories:
検索の起点となるディレクトリパス
戻り値
なし

 find関数の第一引数にはサブルーチンへのリファレンスを渡します。このサブルーチンは検索対象のファイルやディレクトリを1つ検索するごとに1回File::Findから呼び出されます。例えば、特定のファイル名のファイルを探したい場合は、wantedサブルーチンの中で、引数で渡されるファイル名を判定すればよいわけです。

 find関数の第二引数には検索の起点となるパスを渡します。複数のディレクトリを検索したい場合は、リストで渡すこともできます。上のサンプルの「find test 2」は複数のパスを渡している例です。

 さらに、第一引数はハッシュへのリファレンスを渡して、File::Findで使われるオプションを同時に設定することもできます。上のサンプルの「find test 3」は第一引数でオプションを設定している例です。

 指定できるオプションには次のようなものがあります。

オプション
意味
bydepth
1の場合、深さ方向優先の探索を行う。finddepth関数と同等の動作になる。

 上のサンプルでは「find test 3」でbydepthオプションを指定しています。これを指定すると、あるディレクトリよりも、その中のファイルやディレクトリが先に探索されます。「find test 1」と「find test 3」の出力の違いを見比べてみてください。

 File::Findにはもう一つ、finddepthという関数が用意されています。この関数はfind関数でbydepthオプションを指定したのと同等の動作をします。

File::Find::finddepth
findとほぼ同じだが、深さ方向優先の探索を行う。
書式
finddepth \&wanted, @directories
finddepth \%options, @directories
引数
wanted:
サブルーチンへのリファレンス
options:
wantedサブルーチンやオプションを指定したハッシュへのリファレンス
directories:
検索の起点となるディレクトリパス
戻り値
なし

 さて、1度find関数を実行すると、ファイルやディレクトリを1つ検索するたびにwantedサブルーチンが呼び出されますが、今探索されているファイルのファイル名は、wantedサブルーチンの引数で渡されます。これ以外にディレクトリ名なども知りたい場合は、File::Find内に用意されている変数を参照することができます。参照できる変数には次のものがあります。

変数名
意味
$File::Find::dir
現在のディレクトリ名
$File::Find::name
現在のファイルパス($File::Fine::dir/$_と同等)
$File::Find::prune
真の場合、サブディレクトリに対する再帰処理を行わない。
$File::Find::dont_use_nlink
Andrew File Sytem(AFS)を使用している場合は、この変数をセットする。

 上の変数のうち、$File::Find::pruneは少し特殊で、現在探索されているディレクトリのサブディレクトリを再帰的に探索したくない場合は、wantedサブルーチンの中で1をセットします。

 以上がFile::Findの基本的な使い方ですが、File::Findはさらに応用的な使い方をすることもできます。詳しくはファイルの検索2を参照してください。