PHP でディレクトリ内を全走査してファイルを操作(高度なギャグ)するときの方法を調べました。 たまにしかやらないから全然身につかないです。
今回は下記のようなファイル構造で target
以下のファイルを操作する場合を考えます。
~/file_test » tree ./ ./ ├── file.php └── target ├── dir │ └── fuga.png └── hoge.png 2 directories, 3 files
scandir
scandir は指定されたパスのファイルとディレクトリのリストを取得します。
.
と ..
が含まれていたり、下層ディレクトリ内のファイルは取得してくれません。除外したり再帰的に取得しないといけないので、ちょっと使い勝手が悪いです。
取得できる値はファイル / ディレクトリ名の文字列です
<?php var_dump(scandir($targetDirectory)); /* array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(3) "dir" [3]=> string(8) "hoge.png" } */
DirectoryIterator
DirectoryIterator もありますが、scandir と同じく .
と ..
が含まれていたり、下層ディレクトリ内のファイルは取得してくれないです。
イテレーションして取れる値は DirectoryIterator 型です。
<?php foreach (new \DirectoryIterator($targetDirectory) as $item) { var_dump($item); }
FilesystemIterator
FilesystemIterator は DirectoryIterator に少し毛が生えた感じのやつです。 コンストラクタでフラグを指定できて、動作を変えられます。
FilesystemIterator::SKIP_DOTS
のフラグ(デフォルト有効)を渡すと結果に .
と ..
が含まれなくなります。
イテレーションして取れる値は SplFileInfo 型です。
<?php foreach (new \FilesystemIterator($targetDirectory) as $item) { var_dump($item); }
RecursiveIteratorIterator と RecursiveDirectoryIterator
結論、これを使えば楽にファイルだけを操作できます。
RecursiveDirectoryIterator
が下層へアクセスする getChildren
を実装していて、RecursiveIteratorIterator
と組み合わせることで一度のイテレーションで下層を含めたすべてのファイルを操作できます。
RecursiveDirectoryIterator
も RecursiveIteratorIterator
もフラグを指定できて、
下記のように、対象のディレクトリに対して何をどのように取得するかをフラグで指定できます。
RecursiveIteratorIterator::LEAVES_ONLY
のフラグ(デフォルト有効)を渡すと結果はファイルだけのイテレータになります。
<?php foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $targetDirectory, \FilesystemIterator::SKIP_DOTS // `.`, `..` をスキップ | \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO // SplFileInfo として取得 ), \RecursiveIteratorIterator::LEAVES_ONLY // ファイルだけ取得 ) as $item ) { var_dump($item); }
フラグの指定とか長いし new がたくさん出てきたりとかするので、何度も使う場合は適当に関数でラップするといい感じになるかもしれないです。
RecursiveIteratorIterator は結構面白いことができるので、マニュアル を読んでみるといいかもしれません。
以下は、調査用に作った PHP ファイルのソースと実行結果です。
<?php declare(strict_types=1); $targetDirectory = 'target/'; var_dump('---- scandir ----------------------'); var_dump(scandir($targetDirectory)); var_dump('---- DirectoryIterator ------------'); foreach (new \DirectoryIterator($targetDirectory) as $item) { var_dump($item); } var_dump('---- FilesystemIterator -----------'); foreach (new \FilesystemIterator($targetDirectory) as $item) { var_dump($item); } var_dump('---- RecursiveIteratorIterator ----'); foreach ( new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $targetDirectory, \FilesystemIterator::SKIP_DOTS // `.`, `..` をスキップ | \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO // SplFileInfo として取得 ), \RecursiveIteratorIterator::LEAVES_ONLY // ファイルだけ取得 ) as $item ) { var_dump($item); }
~/file_test » php file.php string(35) "---- scandir ----------------------" array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(3) "dir" [3]=> string(8) "hoge.png" } string(35) "---- DirectoryIterator ------------" object(DirectoryIterator)#1 (4) { ["pathName":"SplFileInfo":private]=> string(8) "target/." ["fileName":"SplFileInfo":private]=> string(1) "." ["glob":"DirectoryIterator":private]=> bool(false) ["subPathName":"RecursiveDirectoryIterator":private]=> string(0) "" } object(DirectoryIterator)#1 (4) { ["pathName":"SplFileInfo":private]=> string(9) "target/.." ["fileName":"SplFileInfo":private]=> string(2) ".." ["glob":"DirectoryIterator":private]=> bool(false) ["subPathName":"RecursiveDirectoryIterator":private]=> string(0) "" } object(DirectoryIterator)#1 (4) { ["pathName":"SplFileInfo":private]=> string(15) "target/hoge.png" ["fileName":"SplFileInfo":private]=> string(8) "hoge.png" ["glob":"DirectoryIterator":private]=> bool(false) ["subPathName":"RecursiveDirectoryIterator":private]=> string(0) "" } object(DirectoryIterator)#1 (4) { ["pathName":"SplFileInfo":private]=> string(10) "target/dir" ["fileName":"SplFileInfo":private]=> string(3) "dir" ["glob":"DirectoryIterator":private]=> bool(false) ["subPathName":"RecursiveDirectoryIterator":private]=> string(0) "" } string(35) "---- FilesystemIterator -----------" object(SplFileInfo)#4 (2) { ["pathName":"SplFileInfo":private]=> string(15) "target/hoge.png" ["fileName":"SplFileInfo":private]=> string(8) "hoge.png" } object(SplFileInfo)#1 (2) { ["pathName":"SplFileInfo":private]=> string(10) "target/dir" ["fileName":"SplFileInfo":private]=> string(3) "dir" } string(35) "---- RecursiveIteratorIterator ----" object(SplFileInfo)#6 (2) { ["pathName":"SplFileInfo":private]=> string(15) "target/hoge.png" ["fileName":"SplFileInfo":private]=> string(8) "hoge.png" } object(SplFileInfo)#8 (2) { ["pathName":"SplFileInfo":private]=> string(19) "target/dir/fuga.png" ["fileName":"SplFileInfo":private]=> string(8) "fuga.png" }