Recursive delete

ぐ巨炮叔叔 提交于 2019-12-12 07:16:10

问题


I have this code to recursive delete files and directories. It works fine but has a little problem. If $path = /var/www/foo/ it will delete everything inside of foo, but not foo. I want to delete foo directory too. Any idea?

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);
                }
            }
        }
    }
}

回答1:


Why even recurse in your function?

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);
}

It works, because RII::CHILD_FIRST iterates over the children before the parent element. So by the time it reaches the directory, it should be empty.

But the actual error is due to where you delete your directories. In inner directories you do it in the parent iteration. That means that your root directory will never be deleted. I'd suggest doing it in the local delete iteration:

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);
}

Note the two changes. We're only deleting the empty directories inside of the iteration. Calling $this->delete() on it will handle the deletion for you. The second change is the addition of the final rmdir at the end of the method...




回答2:


You're missing one last rmdir. You could either call it after $this->delete($path) like this:

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

Or you could change the foreach-loop like this:

public function delete($path) {
    //snip

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

    rmdir($path);
}

Also, I sure hope you validate what paths you get there, if this is visible to a user (like a "Delete Everything On My Webspace"-function. I mean, you'll have a lot of fun if somebody passes /etc/ into there.




回答3:


try this

unset( $directoryIterator); rmdir($filePath);




回答4:


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);
}

?



来源:https://stackoverflow.com/questions/4490637/recursive-delete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!