Reputation: 5014
I am using PHP to move the contents of a images subfolder
GalleryName/images/
into another folder. After the move, I need to delete the GalleryName directory and everything else inside it.
I know that rmdir()
won't work unless the directory is empty. I've spent a while trying to build a recursive function to scandir()
starting from the top and then unlink()
if it's a file and scandir()
if it's a directory, then rmdir()
each empty directory as I go.
So far it's not working exactly right, and I began to think -- isn't this a ridiculously simple function that PHP should be able to do? Removing a directory?
So is there something I'm missing? Or is there at least a proven function that people use for this action?
Any help would be appreciated.
PS I trust you all here more than the comments on the php.net site -- there are hundreds of functions there but I am interested to hear if any of you here recommend one over others.
Upvotes: 28
Views: 34669
Reputation: 5305
What about this?
function rmdir_recursive($dirPath){
if(!empty($dirPath) && is_dir($dirPath) ){
$dirObj= new RecursiveDirectoryIterator($dirPath, RecursiveDirectoryIterator::SKIP_DOTS); //upper dirs not included,otherwise DISASTER HAPPENS :)
$files = new RecursiveIteratorIterator($dirObj, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($files as $path)
$path->isDir() && !$path->isLink() ? rmdir($path->getPathname()) : unlink($path->getPathname());
rmdir($dirPath);
return true;
}
return false;
}
Upvotes: 91
Reputation: 328
If the server of application runs linux, just use the shell_exec() function, and provide it the rm -R command, like this:
$realPath = realpath($dir_path);
if($realPath === FALSE){
throw new \Exception('Directory does not exist');
}
shell_exec("rm ". escapeshellarg($realPath) ." -R");
Explanation:
Removes the specified directory recursively only if the path exists and escapes the path so that it can only be used as a shell argument to avoid shell command injection.
If you wouldnt use escapeshellarg
one could execute commands by naming the directory to be removed after a command.
Upvotes: 2
Reputation: 1372
public static function rrmdir($dir)
{
if (is_dir($dir)) {
$files = scandir($dir);
foreach ($files as $file) {
if ($file != "." && $file != "..") {
if (filetype($dir . "/" . $file) == "dir")
self::rrmdir($dir . "/" . $file);
else
unlink($dir . "/" . $file);
}
}
reset($files);
rmdir($dir);
}
}
Upvotes: 0
Reputation: 31
I prefer an enhaced method derived from the php help pages http://php.net/manual/en/function.rmdir.php#115598
// check accidential empty, root or relative pathes
if (!empty($path) && ...)
{
if (PHP_OS === 'Windows')
{
exec('rd /s /q "'.$path.'"');
}
else
{
exec('rm -rf "'.$path.'"');
}
}
else
{
error_log('path not valid:$path'.var_export($path, true));
}
reasons for my decision:
Upvotes: 0
Reputation: 5014
This is the recursive function I've created/modifed and that finally seems to be working. Hopefully there isn't anything too dangerous in it.
function destroy_dir($dir) {
if (!is_dir($dir) || is_link($dir)) return unlink($dir);
foreach (scandir($dir) as $file) {
if ($file == '.' || $file == '..') continue;
if (!destroy_dir($dir . DIRECTORY_SEPARATOR . $file)) {
chmod($dir . DIRECTORY_SEPARATOR . $file, 0777);
if (!destroy_dir($dir . DIRECTORY_SEPARATOR . $file)) return false;
};
}
return rmdir($dir);
}
Upvotes: 14
Reputation: 20431
I've adapted a function which handles hidden unix files with the dot prefix and uses glob:
public static function deleteDir($path) {
if (!is_dir($path)) {
throw new InvalidArgumentException("$path is not a directory");
}
if (substr($path, strlen($path) - 1, 1) != '/') {
$path .= '/';
}
$dotfiles = glob($path . '.*', GLOB_MARK);
$files = glob($path . '*', GLOB_MARK);
$files = array_merge($files, $dotfiles);
foreach ($files as $file) {
if (basename($file) == '.' || basename($file) == '..') {
continue;
} else if (is_dir($file)) {
self::deleteDir($file);
} else {
unlink($file);
}
}
rmdir($path);
}
Upvotes: 0