How do I remove a directory that is not empty?
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);