Skip to content
Caution: You are browsing the legacy symfony 1.x part of this website.

ファイルを見つける方法

Symfony version
Language

概要

アプリケーションのスクリプトの中には必ずしもどこにあるのか知らないままアクセスする必要があります。 bashコマンドを使用しているのであれば、それらを見つけるためにfindが利用できます。 symfonyでは、sfFinderクラスが利用できます。 複雑な検索を行うことは新しい検索基準の問題であり、ファイルパスであれば結果はシンプルな配列です。

sfFinderクラス

sfFinderクラスはPerlのFile::Find::Ruleモジュールに基づいたファイルファインダクラスです。 ファイルもしくはディレクトリ(もしくは両方)を見つけることが可能で、ユーザー定義のルールの設定で検索をフィルタリングできます。基本的な使い方は以下のとおりです:

  1. typeクラスメソッドを呼び出してsfFinderオブジェクトを作成します。何の結果を期待しているのかを正確に記述しなければなりません(filedirもしくはanyのどれか)

    $finder = sfFinder::type('file');
  2. 検索方法を洗練させて結果数を減らすためにルールを追加します

    $finder = $finder->name('*.php');
  3. in()メソッドを呼び出すことで検索機能を起動させ、検索のrootディレクトリを引数として設定します

    $files = $finder->in('/home/production/myproject');

読みやすくするためにメソッドチェーンが利用できます:

$files = sfFinder::type('file')->name('*.php')->in('/home/production/myproject');
// 次のように読むことができる
// '/home/production/myproject'ディレクトリで'*.php'にマッチするファイルを見つける

in()メソッドはファイル操作を簡単に利用できるようにファイルの配列を返します:

foreach ($files as $file)
{
  $handle = fopen($file, "r");
  ...
}

note

sfFinderクラスはオートロードされるのでrequireする必要はありません。

ルールの原則

検索を洗練させるために使われるルールはsfFinderオブジェクトのメソッド呼び出しとして書かれます。 すべてのメソッドは簡単なメソッドチェーンを実現するために現在のsfFinderオブジェクトを返します。

$finder1 = sfFinder::type('file')->name('*.php');                   // はsfFinderオブジェクト
$finder2 = sfFinder::type('file')->name('*.php')->size('> 10K');    // もsfFinderオブジェクト
$files = $finder1->in('/home/production/myproject');                // ファイルパスの配列

in()メソッドを除いて、すべてのルールは何度も起動することがあります。

累積するルール(たとえばname)や破壊なルール(macdepth()など)があります。 破壊的なルールに対しては、最新のメソッドコールだけがカウントします:

// これは両方の条件を満たすファイルの名前をフィルタリングする
$finder = sfFinder::type('file')->name('*.php')->name('*Success.*');
// 同じ
$finder = sfFinder::type('file')->name('*Success.php');
 
// ここでは最後のコールだけが考慮される
$finder = sfFinder::type('file')->maxdepth(5)->maxdepth(3);
// 同じ
$finder = sfFinder::type('file')->maxdepth(3);

フィルターのルール

名前によるフィルター

ファイルの名前の結果をフィルタリングするために、globもしくは正規表現のパターンでname()メソッドへのコールを追加します:

$finder = sfFinder::type('file')->name('*.php');
$finder = sfFinder::type('file')->name('/.*\.php/');

not_name()メソッドでネガティブフィルタリングをすることで、検索結果から特定のファイルの名前を排除できます:

$finder = sfFinder::type('file')->not_name('Base*');
$finder = sfFinder::type('file')->name('/^Base.*$/');

サイズによるフィルタ

引数として比較を含む文字列を要求するsize()メソッドを呼び出すことでファイルサイズ上の検索をフィルタリングできます。 メソッドは規模も理解します:

// 10キロバイトよりも大きいファイルだけを検索する
$finder = sfFinder::type('file')->size('> 10K');
// 1キロバイト以下のファイルだけを検索する
$finder = sfFinder::type('file')->size('<= 1Ki');
// 123バイトのサイズのファイルだけを検索する
$finder = sfFinder::type('file')->size(123);

規模のために使われるシンボルはユニットの内部システムで定義された2進接頭辞(binary prefix)です。

検索の深さを制限する

デフォルトでは、sfFinderオブジェクトによって行われる検索は再帰的ですべてのサブディレクトリを走査します。 フィルタツリー構造で検索の最大の深さを設定するmaxdepth()メソッドを使うすることでこのデフォルトのふるまいをオーバーライドできます:

// ディレクトリとサブディレクトリを検索する
$finder = sfFinder::type('file');
// in()メソッドに渡されたディレクトリのみを検索し
// サブディレクトリは検索しない
$finder = sfFinder::type('file')->maxdepth(1);

もちろん、mindepthメソッドを呼び出すことで最小の深さを指定できます。

デフォルトでは、最小の深さは0で最大の深さは無限です(もしくは無限に近い)。

ディレクトリを除外する

検索からディレクトリを除外したい場合、2つのメソッドが使えます:

  • prune()メソッドは引数として与えられたパターンが見つかるツリー構造の部分で検索を停止させます。 ディレクトリに何があるのかを調べることを停止させる条件と見てください:

    // '.svn'フォルダの内容を無視する
    $finder = sfFinder::type('any')->prune('.svn');

    ファインダは.svnフォルダの奧には進みませんが、.svnフォルダ自身はまだ結果の部分です。

  • discard()メソッドは結果から引数をマッチするファイルもしくはフォルダを除外しますが、ツリー構造の調査は止めません。

    // 結果から'.svn'フォルダを除外する
    $finder = sfFinder::type('any')->discard('.svn');

ディレクトリその内容が検索から除外する必要があるとき、これら2つのメソッドはしばし混同されます:

// 結果から'.svn'フォルダとその内容を除外する
$finder = sfFinder::type('any')->prune('.svn')->discard('.svn');

tip

バージョンコントロールプログラムによって追加されるファイルとディレクトリを除外するために、sfFinderはショートカットメソッド: ignore_version_control()を提供します。 .svnCVS_darcs.arch-params.monotone.bzrのようなディレクトリとファイルをすべて取り除きます。

検索の起点

in()メソッドはsfFinderがファイルもしくはディレクトリを探さなければならない場所を指定するために使用されます。 引数としてファイルパスもしくはファイルパスの配列を受け取ります:

// 単独の場所を検索する
$files = $finder->in('/home/production/myproject');
// 複数の場所を検索する
$files = $finder->in(array('/home/production/myproject', '/home/production/myotherproject'));

絶対もしくは相対パスのどちらかを受け取ることができます:

// 絶対パス
$files = $finder->in('/home/production/myproject');
// 相対パス
$files = $finder->in('../projects/myproject');

相対パスを返す

デフォルトでは、in()メソッドによって返されるパスは絶対パスです。 in()メソッドを呼び出す前にrelative()メソッドへのコールを連結することで、相対パスの配列を受け取ることを選択できます:

// パスの結果はrootディレクトリに対して相対的である
$files = $finder->in('/home/production/myproject');
// パスの結果は現在のディレクトリに対して相対的である
// すなわち現在のスクリプトのディレクトリ
$files = $finder->relative()->in('/home/production/myproject');

This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.