【PHP】ディレクトリ内のファイルを再帰的に検索

PHP

PHPでディレクトリ内のファイルを、深い階層のサブディレクト内も含めて再帰的に検索してリストアップする方法の解説です。

この記事のゴール

RecursiveDirectoryIteratorを使った検索で指定パターンのファイルをリストアップします。

前提条件

  • Ubuntu上で作業しています。
  • PHP8.1以降を想定

検索対象のフォルダ構成

以下の画像のように「level1」を第一階層のフォルダとして、

「level4」までサブフォルダがあります。

各階層に適当に「~.neon」と「~.txt」が配置してあります。

ここから、「*.neon」ファイルだけをリストアップしていきます。

level1/level1.neon
level1/level2/level2.neon
level1/level2/level3/level3.neon
level1/level2/level3/level4/level4.neon
level1/level2_2/level2_2.neon
level1/level2_2/level3/level3.neon
level1/level2_2/level3_2/level4/level4.neon

Linuxコマンドだと

find level1/ -name *.neon | sort

のような処理です。

RecursiveDirectoryIteratorを使った検索

SPL(Standard PHP Library)のイテレータ

PHP: RecursiveDirectoryIterator - Manual

RecursiveDirectoryIterator を使ってディレクトリ内のエントリーをリストアップします。

<?php

$dir = 'level1';
$it = new RecursiveDirectoryIterator($dir);
foreach ($it as $file) {
    echo sprintf(
        "%s/%s\n",
        $file->getPath(),
        $file->getFilename()
    );
}

実行してみます。

フォルダ「level1」内のエントリーがリストアップされました。

サブディレクトリを再帰的に検索するには、

RecursiveIteratorIterator を併せて使います。

<?php

$dir = 'level1';
$it = new RecursiveDirectoryIterator($dir);
$it = new RecursiveIteratorIterator(
    $it,
    RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($it as $file) {
    echo sprintf(
        "%s/%s\n",
        $file->getPath(),
        $file->getFilename()
    );
}

実行してみます。

サブディレクトリの最下層までリストアップできました。

このうち、パターンマッチしたものだけをリストアップします。

RegexIterator をさらに併せて使います。

<?php

$dir = 'level1';
$pattern = '|\.neon$|';
$it = new RecursiveDirectoryIterator($dir);
$it = new RecursiveIteratorIterator(
    $it,
    RecursiveIteratorIterator::LEAVES_ONLY
);
$it = new RegexIterator($it, $pattern);
foreach ($it as $file) {
    echo sprintf(
        "%s/%s\n",
        $file->getPath(),
        $file->getFilename()
    );
}

実行してみます。

結果をソートする場合は、一度配列に格納してソートします。

<?php

$dir = 'level1';
$pattern = '|\.neon$|';
$it = new RecursiveDirectoryIterator($dir);
$it = new RecursiveIteratorIterator(
    $it,
    RecursiveIteratorIterator::LEAVES_ONLY
);
$it = new RegexIterator($it, $pattern);
$matched = [];
foreach ($it as $file) {
    $matched[] = sprintf(
        "%s/%s",
        $file->getPath(),
        $file->getFilename()
    );
}
sort($matched);
echo implode(PHP_EOL, $matched) . PHP_EOL;

実行してみます。

ソートされた結果が表示されました。

以上です。

コメント

タイトルとURLをコピーしました