This article has moved to:
http://bsd-noobz.com/blog/how-to-remove-directories-recursively-with-php

Remove Directories Recursively with PHP

Nov 9, 2008 | Tags: PHP | del.icio.us del.icio.us | digg Digg

At many times we need to empty a directory. Of course PHP has the filesystem functions like unlink() and rmdir() to delete files and directories. At first we may think that simply use rmdir() will solve the problem. Unfortunately it's not. rmdir() only removes empty directory. If the directory is not empty, it will return false.

In order to remove a directory and its contents, we have to remove its contents first, consisting of files and subdirectories. To make things more complicated, the subdirectories also contains files and another subdirectories in it.

It seems like this is a difficult task to solve. But in contrast, this is a very simple recursive function. See the code below.

Listing 1: rmdir_recursive.php

  1. <?php
  2. /*
  3.  * this function removes a directory and its contents.
  4.  * use with careful, no undo!
  5.  */
  6. function rmdir_recursive($dir) {
  7.     $files = scandir($dir);
  8.     array_shift($files);    // remove '.' from array
  9.     array_shift($files);    // remove '..' from array
  10.    
  11.     foreach ($files as $file) {
  12.         $file = $dir . '/' . $file;
  13.         if (is_dir($file)) {
  14.             rmdir_recursive($file);
  15.             rmdir($file);
  16.         } else {
  17.             unlink($file);
  18.         }
  19.     }
  20.     rmdir($dir);
  21. }
  22.  
  23. // remove directory /home/nash/tmp
  24. $dir = '/home/nash/tmp';
  25. rmdir_recursive($dir);
  26. ?>

The function determines if argument is a regular file or a directory. If it is a regular file, it will remove the file. If it is a directory, it will remove its contents first by calling the function itself, and then removes the empty directory.

Note that the function above removes a directory. If what you need is remove directory contents, simply delete the line:

rmdir($dir)

in line 20.

6 Comments

Davo on Jul 29, 2009:

At last!
Someone with a routine that actually works.
I have experimented with code from people that should be writing novels
Yet this simple little recusancy is just the Duck's guts.
Thank you who ever you are... in my book, you are truly a hero.

South Africa PHP developers on Jan 27, 2010:

Thanks, for the code quite a niftly little function but does a good job, also like the fact that its a really small function not lots of long code!

MK on Mar 30, 2010:

I've been searching for this all around and yours is the only one that works, thanks man

Daniel on Apr 8, 2010:

Yo, man. nice piece.
One thought though - if in the dir there are nodes starting with any of the symbols above the number on the keyboard including space (that is all chars that stand before the `.` in the ascii table then

array_shift($files);

will not remove both `.` nodes and the results will be ... well it will break
You should make a check for `.` and `..` explicitly in the node loop.

Regards

Nash on Apr 9, 2010:

Good suggestion. Thanks, Daniel.

Will Smelser on Apr 29, 2010:

Good clean code. Thanks for saving me a wee bit of time. See so much php 4 and early clunky code out there. Good to see php 5 methods picking up steam, but Daniel is correct. here is fun version:

function rmdir_rec($dir,$skipFiles=array('.','..'))
{
  $dir .= (substr($dir,0,-1) == '/') ? '' : '/';
  foreach (scandir($dir) as $file)
  {
    if(in_array($file,$skipFiles) === false)
    {
      if(is_dir($dir.$file)) rmdir_rec($dir.$file);
      (is_dir($dir.$file)) ? rmdir($dir.$file) : unlink($dir.$file);
    }
  }
}

Comment is closed.