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.

2763 views
d

By. Jacob

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.

Tell us what you think:

  1. An in-dept look at the use of headings (h1-h6) and sections in HTML pages.
  2. Pagination can be a confusing thing to get right both practically and programmatically. I have put a lot of thought into this subject, and here I am giving you a few of the ideas I have been working with.
  3. The best way to deal with a trailing question mark is probably just to make it a bad request, because it is a very odd thing to find in a request URL.
  4. How to optimize image-loading and automatically include width and height attributes on img elements with PHP.
  5. HTTP headers are not case-sensitive, so we are free to convert them to all-lowercase in our applications.

More in: Web development