4

ファイルとディレクトリを再帰的に削除するためのこのコードがあります。正常に動作しますが、少し問題があります。$path = /var/www/foo/ の場合、foo 内のすべてが削除されますが、foo は削除されません。foo ディレクトリも削除したい。何か案が?

public function delete($path) {
    if(!file_exists($path)) {
        throw new RecursiveDirectoryException('Directory doesn\'t exist.');
    }

    $directoryIterator = new DirectoryIterator($path);

    foreach($directoryIterator as $fileInfo) {
        $filePath = $fileInfo->getPathname();

        if(!$fileInfo->isDot()) {
            if($fileInfo->isFile()) {
                unlink($filePath);
            }
            else if($fileInfo->isDir()) {
                if($this->emptyDirectory($filePath)) {
                    rmdir($filePath);
                }
                else {
                    $this->delete($filePath);
                    rmdir($filePath);
                }
            }
        }
    }
}
4

4 に答える 4

12

関数で再帰するのはなぜですか?

public function delete($path) {
    $it = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($it as $file) {
        if (in_array($file->getBasename(), array('.', '..'))) {
            continue;
        } elseif ($file->isDir()) {
            rmdir($file->getPathname());
        } elseif ($file->isFile() || $file->isLink()) {
            unlink($file->getPathname());
        }
    }
    rmdir($path);
}

RII::CHILD_FIRST親要素の前に子を反復するため、機能します。したがって、ディレクトリに到達するまでには、空になっているはずです。

しかし、実際のエラーは、ディレクトリを削除した場所が原因です。内部ディレクトリでは、親反復でそれを行います。つまり、ルート ディレクトリが削除されることはありません。ローカル削除の繰り返しで行うことをお勧めします。

public function delete($path) {
    if(!file_exists($path)) {
        throw new RecursiveDirectoryException('Directory doesn\'t exist.');
    }

    $directoryIterator = new DirectoryIterator($path);

    foreach($directoryIterator as $fileInfo) {
        $filePath = $fileInfo->getPathname();
        if(!$fileInfo->isDot()) {
            if($fileInfo->isFile()) {
                unlink($filePath);
            } elseif($fileInfo->isDir()) {
                if($this->emptyDirectory($filePath)) {
                    rmdir($filePath);
                } else {
                    $this->delete($filePath);
                }
            }
        }
    }
    rmdir($path);
}

2 つの変更点に注意してください。反復内の空のディレクトリのみを削除しています。それを呼び出す$this->delete()と、削除が処理されます。2 番目の変更はrmdir、メソッドの最後に final を追加することです...

于 2010-12-20T14:51:35.330 に答える
3

最後の 1 つがありませんrmdir$this->delete($path)次のように呼び出すこともできます。

$this->delete($path);
rmdir($path);

foreachまたは、次のように -loopを変更できます。

public function delete($path) {
    //snip

    foreach($directoryIterator as $fileInfo) {
        //snip
                else {
                    $this->delete($filePath);
                }
            }
        }
    }

    rmdir($path);
}

また、これがユーザーに表示される場合は、そこにたどり着いたパスを検証してください(「私のウェブスペースのすべてを削除する」機能など)/etc/

于 2010-12-20T14:49:20.727 に答える
0

これを試して

unset( $directoryIterator); rmdir($ファイルパス);

于 2013-07-01T10:42:06.137 に答える
-1
function delete($path){
    if(!file_exists($path)) {
        throw new RecursiveDirectoryException('Directory doesn\'t exist.');
    }

    $directoryIterator = new DirectoryIterator($path);

    foreach($directoryIterator as $fileInfo) {
        $filePath = $fileInfo->getPathname();

        if(!$fileInfo->isDot()) {
            if($fileInfo->isFile()) {
                unlink($filePath);
            }
            else if($fileInfo->isDir()) {
                if($this->emptyDirectory($filePath)) {
                    rmdir($filePath);
                }
                else {
                    $this->delete($filePath);
                    rmdir($filePath);
                }
            }
        }
    }
    rmdir($path);
}

?

于 2010-12-20T14:50:31.897 に答える