Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove a directory that is not empty?

Tags:

directory

php

People also ask

How do I delete a non empty directory?

Shutil rmtree() to Delete Non-Empty Directory The rmtree('path') deletes an entire directory tree (including subdirectories under it). The path must point to a directory (but not a symbolic link to a directory).

How do I delete a full directory?

To remove a directory and all its contents, including any subdirectories and files, use the rm command with the recursive option, -r . Directories that are removed with the rmdir command cannot be recovered, nor can directories and their contents removed with the rm -r command.

What is a non empty directory?

The non-empty directory means the directory with files or subdirectories. We can delete the directory by using the Delete() method of the Directory class.


There is no built-in function to do this, but see the comments at the bottom of http://us3.php.net/rmdir. A number of commenters posted their own recursive directory deletion functions. You can take your pick from those.

Here's one that looks decent:

function deleteDirectory($dir) {
    if (!file_exists($dir)) {
        return true;
    }

    if (!is_dir($dir)) {
        return unlink($dir);
    }

    foreach (scandir($dir) as $item) {
        if ($item == '.' || $item == '..') {
            continue;
        }

        if (!deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }

    }

    return rmdir($dir);
}

You could just invoke rm -rf if you want to keep things simple. That does make your script UNIX-only, so beware of that. If you go that route I would try something like:

function deleteDirectory($dir) {
    system('rm -rf -- ' . escapeshellarg($dir), $retval);
    return $retval == 0; // UNIX commands return zero on success
}

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

You could always try to use system commands.

If on linux use: rm -rf /dir If on windows use: rd c:\dir /S /Q

In the post above (John Kugelman) I suppose the PHP parser will optimize that scandir in the foreach but it just seems wrong to me to have the scandir in the foreach condition statement.
You could also just do two array_shift commands to remove the . and .. instead of always checking in the loop.


Can't think of an easier and more efficient way to do that than this

function removeDir($dirname) {
    if (is_dir($dirname)) {
        $dir = new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS);
        foreach (new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST) as $object) {
            if ($object->isFile()) {
                unlink($object);
            } elseif($object->isDir()) {
                rmdir($object);
            } else {
                throw new Exception('Unknown object type: '. $object->getFileName());
            }
        }
        rmdir($dirname); // Now remove myfolder
    } else {
        throw new Exception('This is not a directory');
    }
}


removeDir('./myfolder');

Here what I used:

function emptyDir($dir) {
    if (is_dir($dir)) {
        $scn = scandir($dir);
        foreach ($scn as $files) {
            if ($files !== '.') {
                if ($files !== '..') {
                    if (!is_dir($dir . '/' . $files)) {
                        unlink($dir . '/' . $files);
                    } else {
                        emptyDir($dir . '/' . $files);
                        rmdir($dir . '/' . $files);
                    }
                }
            }
        }
    }
}

$dir = 'link/to/your/dir';
emptyDir($dir);
rmdir($dir);

My case had quite a few tricky directories (names containing special characters, deep nesting, etc) and hidden files that produced "Directory not empty" errors with other suggested solutions. Since a Unix-only solution was unacceptable, I tested until I arrived at the following solution (which worked well in my case):

function removeDirectory($path) {
    // The preg_replace is necessary in order to traverse certain types of folder paths (such as /dir/[[dir2]]/dir3.abc#/)
    // The {,.}* with GLOB_BRACE is necessary to pull all hidden files (have to remove or get "Directory not empty" errors)
    $files = glob(preg_replace('/(\*|\?|\[)/', '[$1]', $path).'/{,.}*', GLOB_BRACE);
    foreach ($files as $file) {
        if ($file == $path.'/.' || $file == $path.'/..') { continue; } // skip special dir entries
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}