2

I have the following recursive method to delete a directory and all its sub-directories and files:

protected function _rrmdir($dir)
{
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != '.' && $object != '..') {
                if (filetype($dir . '/' . $object) == 'dir') {
                    _rrmdir($dir . '/' . $object);
                } else {
                    unlink($dir . '/' . $object);
                }
            }
        }

        reset($objects);
        rmdir($dir);
    }
}

On occasion, the get a Warning, "Directory not empty".

The directory is actually created as a temporary holder for files. The files are downloaded from the Internet using the following snippet:

file_put_contents($filename, file_get_contents($file))

After they are downloaded (a write operation), they are then uploaded to a website (a read operation). Once done uploading, the temporary folder and its files are then deleted.

The odd thing is that when I look inside the temporary folder, there are no files there. It's as if the code tried to delete the folder while the last file was in the process of being deleted?

Any ideas what might be wrong and how to resolve it? I need this code to run on Windows and *nix, so a *nix only solution is not an option.

3
  • 1
    Are there per chance 'dotfiles' in the directory? (these may not show up in list commands if the php user is not allowed to see them). Similar applies to windows for hidden files and .db files. When you try to remove these files, they may also be in use preventing their deletion but i suspect that would throw an error or warning. Commented Jun 12, 2017 at 9:41
  • No "dotfiles". The files downloaded to the folder are images (mainly JPGs). These folders are getting created just to be a temporary container for these images. Nothing else done in the folder. Commented Jun 12, 2017 at 10:01
  • try changing the line if (filetype($dir . '/' . $object) == 'dir') { by if (is_dir($dir . '/' . $object)) { as you do at the start of your method. Commented Jun 12, 2017 at 10:10

1 Answer 1

1

The constant DIRECTORY_SEPARATOR might help you with Windows/Unix compatibility. For the folder not empty, try this:

protected function _rrmdir($dir)
{
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != '.' && $object != '..') {
                if (is_dir($dir . DIRECTORY_SEPARATOR . $object)) {
                    _rrmdir($dir . DIRECTORY_SEPARATOR . $object);
                } else {
                    if( is_file($dir . DIRECTORY_SEPARATOR . $object) ) {
                        if(!unlink($dir . DIRECTORY_SEPARATOR . $object)) {
                            // code in case the file was not removed
                        }
                        // wait a bit here?
                    } else {
                        // code for debug file permission issues
                    }
                }
            }
        }
        reset($objects);
        rmdir($dir);
    }
}

It might happen that you try to remove a file which permissions are not at php exec level.
The is_file() method will return FALSE only if no read permissions, mind that write permissions are needed by the execution owner to delete files.

Sign up to request clarification or add additional context in comments.

3 Comments

Testing your code. Remember, the problem was very intermittent. Thanks for suggestion to use DIRECTORY_SEPARATOR and is_file().
I still get the problem (the folder is not deleted) intermittently. The difference now is that I no longer get the warning about Directory Not Empty. Must be a problem with rmdir()?
mmm... intermittency in the action, it could be due that the recursive stack sometimes gets empty before the os actually deleted "the last file" in the folder, then, when the top element in the execution stack arrives (father folder), the os didn't released the link to the file that causes the warning. In which os are you working? If this is true, maybe getting the response of unlink like $result=unlink(...) or a little sleep after the unlink command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.