Share via:

Recursively Delete Directories

In this tutorial I show how to create a simple_delete() function in PHP to automatically delete whatever you ask it, and also handle errors.

1056 views

Edited: 2019-10-16 21:23

wow PHP, server-sided scripting language.

The rmdir function of PHP is a bit unintuitive, since it does not work the way most users expect. Deleting directories is unnecessarily complicated. Personally, I would prefer a single function to delete both files and directories, as well as non-empty directories. Deleting a directory with content should be handled automatically. Currently, it is not. So, we have to come up with our own complex solution.

In Linux, you can at least use the rm -rf [some_directory] to forcefully remove a directory that is not empty, but in PHP there is no equivalent and it also will not work in Windows. So, we have to code our own function.

Luckily, such tasks are not impossibly hard, and they serve as nice learning exercises. Before you just copy and paste the solution in this article, you may want to try and come up with your own :-)

The solution is to create a looping mechanism, which will recursively delete any files and subdirectories within the main directory. Since it is possible for a function to call itself, someone has suggested that we do something similar to the below, and I simply tried to improve it by handling errors:

function simple_delete($file_or_dir)
{
    if (is_writable($file_or_dir)) { // Check for write permissions

        if (is_dir($file_or_dir)) { // Do this if we are dealing with a directory

            // Make sure we have a slash at the end if dealing with a directory
            $file_or_dir = rtrim($file_or_dir, '/') . '/';

            $objects = glob($file_or_dir . '*'); // Handle subdirectories (if any)

            foreach ($objects as $object) {
                if (is_dir($object)) {
                    simple_delete($object); // If dealing with a subdirectory, perform another simple_delete()
                } else {
                    if (is_writable($object)) { // Check for write permissions
                        unlink($object); // Delete file
                    } else {return false;}
                }
            }
            rmdir($file_or_dir); // Delete directory
            return true; // Return true on success
        } else {
            unlink($file_or_dir); // simple_delete() also works on single files
        }
    } else {return false;}
}

To call the function, and handle errors in a general manner, simply perform a if check, like this:

define('BASE_PATH', rtrim(realpath(dirname(__FILE__)), "/") . '/');

$dir = BASE_PATH . 'test/';

header('Content-type: text/txt');

if(simple_delete($dir)) {
  echo 'Deleted - Ok!';
} else {
  echo 'Error: unable to perform delete. This may be a problem with permissions.';
}

rmdir and Directory not empty

Typically using rmdir on a non-empty directory will not work as we intuitively expect, and instead it will result in an error like the below:

Warning: rmdir(dirname): Directory not empty in /var/www/mysite/some_file.php on line 12

I think the fine control that unlink and rmdir provides still have its place in some cases. However, most the time I just want to perform a delete and move on, without having to think about whether something is a directory or a file.

This is why i named the function simple_delete(). I wanted a function that would delete whatever I was feeding it, regardless of whether it is a directory, file, or a directory with content in it.

For more complex file handling situations and better error handling, I recommend using Beamtic's file handler class.

Comments