LoginSignup
2
3

More than 5 years have passed since last update.

RecursiveDirectoryIteratorで親ディレクトリまで対象に入る

Last updated at Posted at 2018-10-15

前書き

ぼく「/var/www/tmp/以下にある全部のディレクトリを削除したいな~」
ぼく「/var/www/以下が全部消えた…」

ダメなコード

dame.php
<?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が実行されてしまいます。

大丈夫なコード

ok.php
<?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も吹き飛ぶので気を付けようね!

2
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3