[PHP]ディレクトリを再帰的に削除する_SPL版
Read More
PHP5からは、SPL(Standard PHP Library)というライブラリが利用することができる。
大量のファイルが内包されたディレクトリを削除する場合、
何も考えずにscandir()を使うと配列に格納する段階でバッファオーバーフローを起こしてしまうことがある。
しかし、RecursiveIteratorIteratorクラスを使い配列ではなくオブジェクトとして扱うことで
このバッファオーバーフローを防ぐことができる。
このSPLイテレータを使ってディレクトリを再帰的に削除するものを実装する。
■ディレクトリを再帰的に削除する(SPL利用)
function rmdir_r($dir_path=null) { $chk=true; // check if(!strlen($dir_path)) return false; if(!file_exists($dir_path)) return true; // 存在しない場合は削除したものとみなす if(!is_dir($dir_path)) return false; if(basename($dir_path)==='.' or basename($dir_path)==='..') return false; // 危険なので禁止 // main $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir_path, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach($files as $file) { if($file->isDir()) { if($chk) $chk = rmdir($file->getPathname()); } else { if($chk) $chk = unlink($file->getPathname()); } } unset($files); if($chk) $chk = rmdir($dir_path); return $chk; }
上記は入れ子になっているディレクトリや内包するファイルも消える。
--
なおRecursiveIteratorIteratorクラスを使わずとも、
dir()やopendir()を使ってもバッファオーバーフローの対策を取ったようなものは実装できる。
function rmdir_r($dir_path=null) { if(!strlen($dir_path)) return false; if(!file_exists($dir_path)) return true; if(is_file($dir_path) or is_link($dir_path)) return @unlink($dir_path); $objDir = @dir($dir_path); while($fl=$objDir->read()) { if($fl==='.' or $fl==='..') continue; if(!rmdir_r($dir_path. '/'. $fl)) return false; } $objDir->close(); return @rmdir($dir_path); }
こんな感じで動くと思う(たぶん)
ただ、この場合ディレクトリの入れ子の数によってメモリが増えていく(たぶん)
未検証。
--
昔と違って使えるメモリ量は多くなっているのでscandir()を使っていても問題になるようなことはあまりないのだけど。
暇があればそれぞれの動作速度をそのうち検証してみたい。
-- 2017/06/19 プログラムを一部修正
別プログラムの話だがRecursiveIteratorIteratorクラスを使ってディレクトリを削除する際に、
クラスオブジェクトが残っていたらエラーが出ることがあったのでunset()する処理を追加。
ERROR: Exception Message: rmdir({$target_file_path}): Directory not empty file: {$exe_file_path}({$line})※変数部分は自分の環境のものへ適時読み替え
Category "PHP" の最新記事
- [PHP]FuelPHPでRequestクラスのレスポンス内容がおかしくなる (0)
- [PHP]null値ならデフォルト値を返すifnull()の使い方 (0)
- [PHP]効率よくFTP上のファイルの存在を確認する方法 (0)
- [PHP]効率よくFTP上のファイル情報を取得する方法 (0)
- シェルで文字に色を付ける方法と色の種類 (0)
- [PHP]フォルダパスの末尾のスラッシュを削除する (0)
- [PHP]ZipArchiveクラスを使ってzipファイルを作成する (0)
- [PHP]ZipArchiveクラスを使ってzipファイルを解凍する (0)
- [PHP]ディレクトリを再帰的に削除する (0)
- [PHP]親クラスの関数に子クラスから動的にアクセスする方法 (0)