あなたが探しているものは、recursive directory traversingとも呼ばれます。つまり、すべてのディレクトリを調べて、そこにあるサブディレクトリとファイルをリストします。サブディレクトリがある場合は、それも同様にトラバースされます。つまり、再帰的です。
ご想像のとおり、これはソフトウェアを作成するときに必要となる一般的なものであり、PHP はそれをサポートします。RecursiveDirectoryIterator
ディレクトリを再帰的に反復できるようにするものとRecursiveIteratorIterator
、トラバーサルを行うための標準を提供します。次に、次のように、単純な反復ですべてのファイルとディレクトリに簡単にアクセスできますforeach
。
$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
foreach($fileinfos as $pathname => $fileinfo) {
if (!$fileinfo->isFile()) continue;
var_dump($pathname);
}
この例では、最初にトラバースするディレクトリを指定します。私は現在のものを取っています:
$rootpath = '.';
次のコード行は少し長く、ディレクトリ イテレータをインスタンス化し、次にイテレータ-イテレータをインスタンス化して、ツリーのような構造を単一/フラット ループでトラバースできるようにします。
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootpath)
);
これら$fileinfos
は単純な で繰り返されますforeach
:
foreach($fileinfos as $pathname => $fileinfo) {
その中に、すべてのディレクトリを出力からスキップするテストがあります。これは、SplFileInfo
反復されるオブジェクトを使用して行われます。これは、再帰的なディレクトリ反復子によって提供され、ファイルを操作するときに役立つ多くのプロパティとメソッドが含まれています。たとえば、ファイル拡張子、サイズと時間などのベース名情報などを返すこともできます。
if (!$fileinfo->isFile()) continue;
最後に、ファイルへのフル パスであるパス名を出力します。
var_dump($pathname);
出力例は次のようになります (ここでは Windows オペレーティング システムの場合)。
string(12) ".\.buildpath"
string(11) ".\.htaccess"
string(33) ".\dom\xml-attacks\attacks-xml.php"
string(38) ".\dom\xml-attacks\billion-laughs-2.xml"
string(36) ".\dom\xml-attacks\billion-laughs.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-2.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-3.xml"
string(38) ".\dom\xml-attacks\quadratic-blowup.xml"
string(22) ".\dom\xmltree-dump.php"
string(25) ".\dom\xpath-list-tags.php"
string(22) ".\dom\xpath-search.php"
string(27) ".\dom\xpath-text-search.php"
string(29) ".\encrypt-decrypt\decrypt.php"
string(29) ".\encrypt-decrypt\encrypt.php"
string(26) ".\encrypt-decrypt\test.php"
string(13) ".\favicon.ico"
アクセスできないサブディレクトリがある場合、次は例外をスローします。この動作は、 をインスタンス化するときにいくつかのフラグで制御できますRecursiveIteratorIterator
。
$fileinfos = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
これが参考になったことを願っています。これを独自のクラスにラップすることもできます。FilterIterator
ファイルをリストするかどうかの決定をforeach
ループの外に移動するために を提供することもできます。
RecursiveDirectoryIterator
との組み合わせの力は、RecursiveIteratorIterator
その柔軟性から生まれます。上記でカバーされていないものは、いわゆるFilterIterator
s です。私は、それらを組み合わせるために互いに配置された2つの自己記述を利用している別の例を追加すると思いました.
- 1 つは、ドットで始まるすべてのファイルとディレクトリを除外することです (これらは UNIX システムでは隠しファイルと見なされるため、その情報を外部に提供しないでください)。
- リストをファイルのみにフィルタリングしている別のもの。これは、以前はforeach内にあったチェックです。
この使用例のもう 1 つの変更点は、反復のルートパスから始まるサブパスを返すgetSubPathname()
関数を使用することです。つまり、探しているものです。
また、トラバースを防止するSKIP_DOTS
フラグを明示的に追加し(技術的には、フィルターがそれらとディレクトリをフィルター処理するため、実際には必要ありませんが、より正確だと思います)、パスとして返すため、パスの文字列は常に unix-基礎となるオペレーティングシステムに関係なくパスのように、これらの値が後でHTTP経由で要求された場合、通常は良い考えです:.
..
UNIX_PATHS
$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
new FilesOnlyFilter(
new VisibleOnlyFilter(
new RecursiveDirectoryIterator(
$rootpath,
FilesystemIterator::SKIP_DOTS
| FilesystemIterator::UNIX_PATHS
)
)
),
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
);
foreach ($fileinfos as $pathname => $fileinfo) {
echo $fileinfos->getSubPathname(), "\n";
}
$fileinfos
この例は、ビルドの構成が少し異なるものの、前の例と似ています。特にフィルタに関する部分が新しくなりました:
new FilesOnlyFilter(
new VisibleOnlyFilter(
new RecursiveDirectoryIterator($rootpath, ...)
)
),
したがって、ディレクトリ反復子はフィルターに入れられ、フィルター自体は別のフィルターに入れられます。残りは変わりませんでした。
これらのフィルターのコードは非常に単純です。これらのフィルターは、取得または除外するaccept
関数で動作します。true
false
class VisibleOnlyFilter extends RecursiveFilterIterator
{
public function accept()
{
$fileName = $this->getInnerIterator()->current()->getFileName();
$firstChar = $fileName[0];
return $firstChar !== '.';
}
}
class FilesOnlyFilter extends RecursiveFilterIterator
{
public function accept()
{
$iterator = $this->getInnerIterator();
// allow traversal
if ($iterator->hasChildren()) {
return true;
}
// filter entries, only allow true files
return $iterator->current()->isFile();
}
}
そして、それは再びそれです。もちろん、これらのフィルターは他の場合にも使用できます。たとえば、別の種類のディレクトリ リストがある場合。
そして、$rootpath
切り取った別の出力例:
test.html
test.rss
tests/test-pad-2.php
tests/test-pad-3.php
tests/test-pad-4.php
tests/test-pad-5.php
tests/test-pad-6.php
tests/test-pad.php
TLD/PSL/C/dkim-regdom.c
TLD/PSL/C/dkim-regdom.h
TLD/PSL/C/Makefile
TLD/PSL/C/punycode.pl
TLD/PSL/C/test-dkim-regdom.c
TLD/PSL/C/test-dkim-regdom.sh
TLD/PSL/C/tld-canon.h
TLD/PSL/generateEffectiveTLDs.php
.git
または.svn
ディレクトリのトラバーサルや、またはのようなファイルのリストは.builtpath
もう必要ありません.project
。
FilesOnlyFilter
およびの注LEAVES_ONLY
:
フィルタは、オブジェクトに基づいてディレクトリとリンクの使用を明示的に拒否します (存在する通常のファイルのみ)。つまり、ファイル システムに基づく実際のフィルタリングです。ディレクトリ以外のエントリのみを取得する別の方法は、デフォルトのフラグのために
付属しています(ここでも例で使用されています)。このフラグはフィルターとしては機能せず、基礎となるイテレーターに依存しません。繰り返しがブランチを返さないように指定するだけです (ここでは、ディレクトリ イテレータの場合はディレクトリ)。SplFileInfo
RecursiveIteratorIterator
LEAVES_ONLY