前書き
ぼく「/var/www/tmp/
以下にある全部のディレクトリを削除したいな~」
ぼく「/var/www/
以下が全部消えた…」
ダメなコード
<?php
$iterator = new RecursiveDirectoryIterator("/var/www/tmp/");
$iterator = new RecursiveIteratorIterator($iterator);
foreach ($file_infos as $file_info) {
//そのファイルがディレクトリなら
if ($file_info->isDir()) {
exec(escapeshellcmd("rm -rf " . $file_info->getRealPath()));
}
}
これだと、.
や..
まで削除してしまいます。つまり、rm -rf /var/www
が実行されてしまいます。
大丈夫なコード
<?php
$iterator = new RecursiveDirectoryIterator("/var/www/tmp/",FilesystemIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator($iterator,RecursiveIteratorIterator::SELF_FIRST);
$file_infos = iterator_to_array($iterator);
foreach ($file_infos as $file_info) {
//そのファイルがディレクトリなら
if ($file_info->isDir()) {
exec(escapeshellcmd("rm -rf " . $file_info->getRealPath()));
}
}
FilesystemIterator::SKIP_DOTS
を入れることで、.
や..
をスキップします。
ハマったこと
ディレクトリを取得できない
/var/www/tmp/hoge/
に入った時にも.
がスキップされるので、ディレクトリが取得できなくなります(伝われ)
そこで、サブフォルダ内のファイルをまとめて取得するにあるように、RecursiveIteratorIterator
の引数にRecursiveIteratorIterator::SELF_FIRST
を付けると取得できます。
UnexpectedValueException
が投げられる
foreach
の部分、最初は
foreach ($iterator as $file_info) {
と書いていたのですが、こうするとUnexpectedValueException
が出ます。
これはforeach
の中でディレクトリを削除しているので、$iterator
が次の値を取るときに削除されていて取れないみたいな感じの感じだと思います。
そこで、stackoverflowにあるように、iterator_to_array()
を使ってイテレータを配列にしちゃいます。
メモリ使用量は増えますがまあいいや(適当)
最後に
/var/www/html
も吹き飛ぶので気を付けようね!