ウェブ開発やファイル操作において、特定のディレクトリ内のファイルやディレクトリを一括で取得する必要がある場面は多々あります。
PHPには、このような作業を効率的に行うためのツールとして、glob関数が提供されています。
glob関数を使えば、ワイルドカードを駆使して指定ディレクトリ内のファイルやディレクトリを一覧で取得でき、その後の処理に利用することができます。
本記事では、PHPのglob関数を駆使して、ファイルとディレクトリの一括取得を行う方法について詳しく説明します。これにより、効率的なファイル操作やデータ処理を実現するための基本的なスキルを身につけることができるでしょう。
結論:glob関数の最短の使い方
まず結論から。glob()は「パターン」を渡すだけで、マッチしたファイル・ディレクトリのパスを配列で返してくれます。特定ディレクトリの一覧取得なら、次の1〜2行で十分です。
<?php
// カレントディレクトリの .txt ファイルをすべて取得
$files = glob('*.txt');
foreach ($files as $file) {
echo $file . PHP_EOL; // a.txt, b.txt, c.txt ...
}
// 特定ディレクトリを対象にする場合は絶対パスで指定する
$files = glob(__DIR__ . '/logs/*.log');
戻り値は常に配列(マッチが無ければ空配列、エラー時はfalse)です。opendir()とreaddir()のようにハンドルを開いてループする必要がなく、拡張子やパターンでの絞り込みをそのまま書けるのがglob()の特徴です。
glob関数の基本とサンプルコード
PHPのglob関数は指定したパターンにマッチしたパスを配列で取得するための関数です。
指定できるパターンはlibcのglob()関数のルールに基づいており、一般的なシェルで使われるルールに似ています。
以下はglob関数を使用するサンプルコードになります。
<?php
/**
現状のディレクトリ構造
.
├── a.txt
├── b.txt
├── c.txt
├── d.csv
├── dir
│ ├── e.txt
│ ├── f.txt
│ ├── g.txt
│ └── sub
│ ├── h.txt
│ ├── i.txt
│ └── j.txt
├── dir2
│ └── k.txt
└── sample.php
4 directories, 12 files
*/
glob(__DIR__ . '/*');
/**
Array
(
[0] => /path/to/directory/glob/a.txt
[1] => /path/to/directory/glob/b.txt
[2] => /path/to/directory/glob/c.txt
[3] => /path/to/directory/glob/d.csv
[4] => /path/to/directory/glob/dir
[5] => /path/to/directory/glob/sample.php
)
*/
glob('*.txt');
/**
Array
(
[0] => a.txt
[1] => b.txt
[2] => c.txt
)
*/
glob('*/*');
/**
Array
(
[0] => dir/e.txt
[1] => dir/f.txt
[2] => dir/g.txt
[3] => dir/sub
[4] => dir2/k.txt
)
*/
glob('*', GLOB_ONLYDIR);
/**
Array
(
[0] => dir
[1] => dir2
)
*/
glob('{a,b}.txt');
/**
Array
(
)
*/
glob('{a,b}.txt', GLOB_BRACE);
/**
Array
(
[0] => a.txt
[1] => b.txt
)
*/
第1引数にはパターンの指定を行い、第2引数にはフラグ指定が可能です。
指定できるフラグには以下があります。
https://www.php.net/manual/ja/function.glob.php
GLOB_MARK– 各ディレクトリにスラッシュ (Windows ではバックスラッシュ) を追加しますGLOB_NOSORT– ディレクトリに存在するファイルを返します (ソートはされません)。このフラグを使わない場合は、パス名をアルファベット順にソートします。GLOB_NOCHECK– 検索パターンにマッチするファイルが見つからない場合に、 検索パターン自身を返しますGLOB_NOESCAPE– バックスラッシュによるメタ文字のクォートを行いませんGLOB_BRACE– {a,b,c} を展開し「a」、「b」あるいは「c」のいずれかにマッチさせますGLOB_ONLYDIR– パターンにマッチするディレクトリのみを返しますGLOB_ERR– (ディレクトリが読めないなどの) 読み込みエラー時に停止します。デフォルトではエラーは無視されます。
よく使うglobパターン一覧
実際の開発で使用頻度の高いパターンを表にまとめました。目的に応じてパターンとフラグを組み合わせて使います。
| やりたいこと | 書き方 | 取得結果 |
|---|---|---|
| すべてのファイル・ディレクトリ | glob('*') | 隠しファイルを除く全項目 |
| 特定の拡張子だけ | glob('*.txt') | .txt ファイルのみ |
| 複数の拡張子 | glob('*.{jpg,png,gif}', GLOB_BRACE) | 画像ファイルをまとめて取得 |
| ディレクトリだけ | glob('*', GLOB_ONLYDIR) | ディレクトリのみ |
| サブディレクトリを1階層ぶん | glob('*/*') | 1階層下のファイル・ディレクトリ |
| 特定ディレクトリを対象 | glob(__DIR__ . '/logs/*.log') | logs 内の .log ファイル |
| ディレクトリに印を付ける | glob('*', GLOB_MARK) | ディレクトリ末尾に / が付く |
| 先頭1文字が任意 | glob('?.txt') | a.txt, b.txt など1文字名 |
*(任意の文字列)、?(任意の1文字)、[...](文字クラス)、{...}(GLOB_BRACE指定時の候補展開)といったワイルドカードを組み合わせられます。なお*は隠しファイル(.で始まるファイル)にはマッチしない点に注意してください。
globと他のファイル一覧取得方法の違い
PHPでファイル・ディレクトリの一覧を取得する方法はglob()だけではありません。それぞれ得意な場面が異なるため、違いを押さえておくと選びやすくなります。
| 方法 | 戻り値 | パターン絞り込み | 再帰 | 向いている用途 |
|---|---|---|---|---|
glob() | パスの配列 | ◎(ワイルドカード) | ×(自前実装が必要) | 拡張子・パターンで手軽に一覧取得 |
scandir() | ファイル名の配列 | × | × | 1ディレクトリの全項目を単純に列挙 |
opendir() / readdir() | ハンドルを1件ずつ | × | × | 大量ファイルを逐次処理してメモリ節約 |
DirectoryIterator | SplFileInfoオブジェクト | × | × | ファイル情報(サイズ・更新日時等)も扱う |
RecursiveDirectoryIterator | SplFileInfoオブジェクト | × | ◎ | サブディレクトリまで再帰的に走査 |
ざっくり整理すると、拡張子やパターンでサッと絞り込みたいならglob()、単にディレクトリ内をすべて列挙したいならscandir()、サブディレクトリまで潜って再帰的に集めたいならRecursiveDirectoryIteratorが基準になります。scandir()は.や..も結果に含まれるため、glob()のように不要なエントリを気にせず拡張子指定できる点はglob()の利点です。
globを使うときの注意点
- マッチが無いときは空配列、権限エラーなどの失敗時は
falseを返します。foreach前にif ($files === false)で確認しておくと安全です。 - デフォルトでは結果がアルファベット順にソートされます。ソートが不要なら
GLOB_NOSORTで高速化できます。 *は.で始まる隠しファイルにマッチしません。.envなどを取得したい場合はパターンを明示する必要があります。- 再帰的な走査はできないため、サブディレクトリまで潜る場合は
RecursiveDirectoryIteratorの利用を検討してください。
終わりに
以上、PHPのglob関数の使い方について解説しました。
シェルの操作に慣れていればパターンの設定がわかりやすい、シンプルな関数かと思います。
こちらの情報が皆さんのプロジェクトに活用できましたら幸いです。

コメントを残す