PHPTweetこんにちは。「特定ディレクトリ以下のファイル全てに対して処理を行うプログラム」を書く機会というのは、たまにありますね。再帰的」といったワードで検索すると、色々引っかかります。それぞれ一長一短あります。「特定ディレクトリ以下のファイル全てに対して処理を行うプログラム」の様々な実装例を紹介します。$list;}scandir()で指定ディレクトリ配下のファイル・ディレクトリの一覧を取得し、一覧にディレクトリが含まれていればさらに掘り進む、という仕組みです。$dirの最後尾の/を取り除いているこの方法でもできなくはありませんが、考慮する必要のある事柄が多く、大変です。この方法はおすすめしません。$list;}一見すると、1.と大差ないように見えますが、glob()はUnixシェルと同様のワイルドカードが使えます。「*.html」というパターンを指定して、.htmlという拡張子のファイルを取ってくる、といったことが簡単にできます。いうライブラリが付属しています。このライブラリは、PHP5.0.0以降ではデフォルトで使用可能、PHP5.3.0以降では常に使用可能となっています。ファイル/ディレクトリ操作を便利にしてくれるクラスがあるので、紹介します。$list;}RecursiveDirectoryIteratorは、ディレクトリを再帰的に反復処理するためのクラスです。RecursiveDirectoryIteratorオブジェクトは、それ自体は再帰的な反復処理に対応していないため、RecursiveDirectoryIteratorオブジェクトを、さらにRecursiveIteratorIteratorオブジェクトに変換する必要があります。文章にするとややこしいですが、コード例を見れば使い方は直感的に分かると思います。上記コード例では、他のコード例との一貫性のため最終的に配列を返していますが、配列にする必然性はありません。イテレータオブジェクトのままの方が使いやすい場面も多いでしょう。条件に合致したファイルだけをフィルタリングしたい場合、RecursiveFilterIteratorを継承したクラスを用意します。}}RecursiveFilterIteratorを継承するクラスでは、accept()メソッドを実装する必要があります。accept()の中にフィルタリング条件を記述します(この場合、「ディレクトリである」又は「ファイル名の末尾が".html"で終わる」)。$list;}RecursiveDirectoryIteratorオブジェクトを、独自実装したHtmlFilterIteratorのコンストラクタに渡し、最後にHtmlFilterIteratorオブジェクトをRecursiveIteratorIteratorのコンストラクタに渡します。RecursiveDirectoryIteratorを使った場合の利点は、ディレクトリの再帰的な走査を自分で書く必要がないことです。欠点は、各クラスの関係や、持っているメソッドの把握等が必要で、学習コストがかかることです。便利なライブラリ再帰的なディレクトリ操作をサポートしているライブラリもあります。決定版がどれかは分かりませんが、個人的に使ってみて良いと思ったのは、SymfonyコンポーネントのFinderです(Symfonyはフルスタックのフレームワークですが、コンポーネント単位でライブラリとして利用することもできます)。以下のコード例は、Composerでインストールした場合です(Composerを使わない場合、オートローダを用意する必要があります。こちらの記事を参考にしてください)。$list;}再帰的なディレクトリ操作について意識する必要もなく、フィルターのためだけにクラスを作る必要もない、非常に使いやすいライブラリです。私なら、Symfonyコンポーネントを導入可能な環境では、迷わずこのライブラリを使いますね。外部コマンド単にファイルリストが欲しいだけなら、PHPでわざわざロジックを組まなくても、外部コマンドを呼び出せば済みます。"*.html"');system()は、外部コマンドを実行し、その結果を表示します。findは、ファイル検索を行うUnixコマンドですね。いった点で機能が豊富です)。外部コマンドの呼び出しは別プロセスの起動を伴うため、一般に高コストです。ユーザーの入力値をコマンドに反映する場合、セキュリティ的にも危険を伴います。PHPにはファイル操作を行うための関数が揃っているので、基本的にはPHPの標準関数を使ったほうが良いでしょう。以下は、exec()でfindを呼び出す場合の実装例です。そもそも、PHPである必然性は...?PHPアプリケーションの一機能として実装する場合、1〜5のいずれかの方法になると思いますが、日常業務の中で「特定ディレクトリのファイルを一定ルールに従ってコピーしたい」といったニーズに対して、あえてPHPを使う必要はありません。ファイルリストが欲しいだけなら、前述したfindコマンドなどを実行すれば十分です。込み入ったことをやる必要があるなら、PerlやRubyでスクリプトを組むのも良いでしょう。Perlの標準ライブラリに含まれるFile::Findは、とても使いやすいです。Rubyにも、File::Findとよく似たインターフェースのFind.findがあります。以下はRubyのFind.findの例です。SymfonyのFinderほど高機能ではありませんが、シンプルで使いやすいですね。まとめ車輪の再発明を避けるのは重要だけど、どの車輪を選ぶかは悩ましい。byスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。