Delete directory with files in it?

PhpRmdir

Php Problem Overview


I wonder, what's the easiest way to delete a directory with all its files in it?

I'm using rmdir(PATH . '/' . $value); to delete a folder, however, if there are files inside of it, I simply can't delete it.

Php Solutions


Solution 1 - Php

There are at least two options available nowadays.

  1. Before deleting the folder, delete all its files and folders (and this means recursion!). Here is an example:

    public static function deleteDir($dirPath) {
        if (! is_dir($dirPath)) {
            throw new InvalidArgumentException("$dirPath must be a directory");
        }
        if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
            $dirPath .= '/';
        }
        $files = glob($dirPath . '*', GLOB_MARK);
        foreach ($files as $file) {
            if (is_dir($file)) {
                self::deleteDir($file);
            } else {
                unlink($file);
            }
        }
        rmdir($dirPath);
    }
    
  2. And if you are using 5.2+ you can use a RecursiveIterator to do it without implementing the recursion yourself:

    $dir = 'samples' . DIRECTORY_SEPARATOR . 'sampledirtree';
    $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $files = new RecursiveIteratorIterator($it,
                 RecursiveIteratorIterator::CHILD_FIRST);
    foreach($files as $file) {
        if ($file->isDir()){
            rmdir($file->getRealPath());
        } else {
            unlink($file->getRealPath());
        }
    }
    rmdir($dir);
    

Solution 2 - Php

I generally use this to delete all files in a folder:

array_map('unlink', glob("$dirname/*.*"));

And then you can do

rmdir($dirname);

Solution 3 - Php

>what's the easiest way to delete a directory with all its files in it?

system("rm -rf ".escapeshellarg($dir));

Solution 4 - Php

Short function that does the job:

function deleteDir($path) {
	return is_file($path) ?
			@unlink($path) :
			array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

I use it in a Utils class like this:

class Utils {
	public static function deleteDir($path) {
		$class_func = array(__CLASS__, __FUNCTION__);
		return is_file($path) ?
				@unlink($path) :
				array_map($class_func, glob($path.'/*')) == @rmdir($path);
	}
}

With great power comes great responsibility: When you call this function with an empty value, it will delete files starting in root (/). As a safeguard you can check if path is empty:

function deleteDir($path) {
    if (empty($path)) { 
        return false;
    }
	return is_file($path) ?
			@unlink($path) :
			array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

Solution 5 - Php

As seen in most voted comment on PHP manual page about rmdir() (see http://php.net/manual/es/function.rmdir.php), glob() function does not return hidden files. scandir() is provided as an alternative that solves that issue.

Algorithm described there (which worked like a charm in my case) is:

<?php 
    function delTree($dir)
    { 
        $files = array_diff(scandir($dir), array('.', '..')); 

        foreach ($files as $file) { 
            (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); 
        }

        return rmdir($dir); 
    } 
?>

Solution 6 - Php

You may use Symfony's Filesystem (code):

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

(new Filesystem)->remove($dir);

However I couldn't delete some complex directory structures with this method, so first you should try it to ensure it's working properly.


I could delete the said directory structure using a Windows specific implementation:

$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');


And just for the sake of completeness, here is an old code of mine:

function xrmdir($dir) {
    $items = scandir($dir);
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        $path = $dir.'/'.$item;
        if (is_dir($path)) {
            xrmdir($path);
        } else {
            unlink($path);
        }
    }
    rmdir($dir);
}

Solution 7 - Php

This is a shorter Version works great to me

function deleteDirectory($dirPath) {
    if (is_dir($dirPath)) {
        $objects = scandir($dirPath);
        foreach ($objects as $object) {
            if ($object != "." && $object !="..") {
                if (filetype($dirPath . DIRECTORY_SEPARATOR . $object) == "dir") {
                    deleteDirectory($dirPath . DIRECTORY_SEPARATOR . $object);
                } else {
                    unlink($dirPath . DIRECTORY_SEPARATOR . $object);
                }
            }
        }
    reset($objects);
    rmdir($dirPath);
    }
}

Solution 8 - Php

You can try as follows:

/*
 * Remove the directory and its content (all files and subdirectories).
 * @param string $dir the directory name
 */
function rmrf($dir) {
    foreach (glob($dir) as $file) {
        if (is_dir($file)) { 
            rmrf("$file/*");
            rmdir($file);
        } else {
            unlink($file);
        }
    }
}

Solution 9 - Php

I can't believe there are 30+ answers for this. Recursively deleting a folder in PHP could take minutes depending on the depth of the directory and the number of files in it! You can do this with one line of code ...

shell_exec("rm -rf " . $dir);

If you're concerned with deleting the entire filesystem, make sure your $dir path is exactly what you want first. NEVER allow a user to input something that can directly delete files without first heavily validating the input. That's essential coding practice.

Solution 10 - Php

Here you have one nice and simple recursion for deleting all files in source directory including that directory:

function delete_dir($src) { 
    $dir = opendir($src);
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                delete_dir($src . '/' . $file); 
            } 
            else { 
                unlink($src . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
	rmdir($src);

}

Function is based on recursion made for copying directory. You can find that function here: https://stackoverflow.com/questions/2050859/copy-entire-contents-of-a-directory-to-another-using-php

Solution 11 - Php

This one works for me:

function removeDirectory($path) {
	$files = glob($path . '/*');
	foreach ($files as $file) {
		is_dir($file) ? removeDirectory($file) : unlink($file);
	}
	rmdir($path);
	return;
}

Solution 12 - Php

Example for the Linux server: exec('rm -f -r ' . $cache_folder . '/*');

Solution 13 - Php

The Best Solution for me

my_folder_delete("../path/folder");

code:

function my_folder_delete($path) {
	if(!empty($path) && is_dir($path) ){
		$dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS); //upper dirs are not included,otherwise DISASTER HAPPENS :)
		$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST);
		foreach ($files as $f) {if (is_file($f)) {unlink($f);} else {$empty_dirs[] = $f;} } if (!empty($empty_dirs)) {foreach ($empty_dirs as $eachDir) {rmdir($eachDir);}} rmdir($path);
	}
}

p.s. REMEMBER!
dont pass EMPTY VALUES to any Directory deleting functions!!! (backup them always, otherwise one day you might get DISASTER!!)

Solution 14 - Php

What about this:

function recursiveDelete($dirPath, $deleteParent = true){
    foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
        $path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
    }
    if($deleteParent) rmdir($dirPath);
}

Solution 15 - Php

Glob function doesn't return the hidden files, therefore scandir can be more useful, when trying to delete recursively a tree.

<?php
public static function delTree($dir) {
   $files = array_diff(scandir($dir), array('.','..'));
    foreach ($files as $file) {
      (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
    }
    return rmdir($dir);
  }
?>

Solution 16 - Php

I want to expand on the answer by @alcuadrado with the comment by @Vijit for handling symlinks. Firstly, use getRealPath(). But then, if you have any symlinks that are folders it will fail as it will try and call rmdir on a link - so you need an extra check.

$it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
    if ($file->isLink()) {
        unlink($file->getPathname());
    } else if ($file->isDir()){
        rmdir($file->getPathname());
    } else {
        unlink($file->getPathname());
    }
}
rmdir($dir);

Solution 17 - Php

I prefer this because it still returns TRUE when it succeeds and FALSE when it fails, and it also prevents a bug where an empty path might try and delete everything from '/*' !!:

function deleteDir($path)
{
    return !empty($path) && is_file($path) ?
        @unlink($path) :
        (array_reduce(glob($path.'/*'), function ($r, $i) { return $r && deleteDir($i); }, TRUE)) && @rmdir($path);
}

Solution 18 - Php

Litle bit modify of alcuadrado's code - glob don't see files with name from points like .htaccess so I use scandir and script deletes itself - check __FILE__.

function deleteDir($dirPath) {
    if (!is_dir($dirPath)) {
        throw new InvalidArgumentException("$dirPath must be a directory");
    }
    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
        $dirPath .= '/';
    }
    $files = scandir($dirPath); 
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        if (is_dir($dirPath.$file)) {
            deleteDir($dirPath.$file);
        } else {
            if ($dirPath.$file !== __FILE__) {
                unlink($dirPath.$file);
            }
        }
    }
    rmdir($dirPath);
}

Solution 19 - Php

Using DirectoryIterator an equivalent of a previous answer…

function deleteFolder($rootPath)
{	
	foreach(new DirectoryIterator($rootPath) as $fileToDelete)
	{
	    if($fileToDelete->isDot()) continue;
		if ($fileToDelete->isFile())
			unlink($fileToDelete->getPathName());
		if ($fileToDelete->isDir())
			deleteFolder($fileToDelete->getPathName());
	}

	rmdir($rootPath);
}

Solution 20 - Php

Something like this?

function delete_folder($folder) {
    $glob = glob($folder);
    foreach ($glob as $g) {
        if (!is_dir($g)) {
            unlink($g);
        } else {
            delete_folder("$g/*");
            rmdir($g);
        }
    }
}

Solution 21 - Php

you can try this simple 12 line of code for delete folder or folder files... happy coding... ;) :)

function deleteAll($str) {
    if (is_file($str)) {
        return unlink($str);
    }
    elseif (is_dir($str)) {
        $scan = glob(rtrim($str,'/').'/*');
        foreach($scan as $index=>$path) {
            $this->deleteAll($path);
        }            
        return @rmdir($str);
    }
}

Solution 22 - Php

Delete all files in Folder
array_map('unlink', glob("$directory/*.*"));
Delete all .*-Files in Folder (without: "." and "..")
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Now delete the Folder itself
rmdir($directory)

Solution 23 - Php

2 cents to add to THIS answer above, which is great BTW

After your glob (or similar) function has scanned/read the directory, add a conditional to check the response is not empty, or an invalid argument supplied for foreach() warning will be thrown. So...

if( ! empty( $files ) )
{
    foreach( $files as $file )
    {
        // do your stuff here...
    }
}

My full function (as an object method):

	private function recursiveRemoveDirectory( $directory )
	{
	    if( ! is_dir( $directory ) )
	    {
	        throw new InvalidArgumentException( "$directory must be a directory" );
	    }
	    
	    if( substr( $directory, strlen( $directory ) - 1, 1 ) != '/' )
	    {
	        $directory .= '/';
	    }
	    
	    $files = glob( $directory . "*" );
	    
	    if( ! empty( $files ) )
	    {
		    foreach( $files as $file )
		    {
		        if( is_dir( $file ) )
		        {
		            $this->recursiveRemoveDirectory( $file );
		        }
		        else
		        {
		            unlink( $file );
		        }
		    }				
		}
	    rmdir( $directory );
	    
	} // END recursiveRemoveDirectory()

Solution 24 - Php

Here is the solution that works perfect:

function unlink_r($from) {
	if (!file_exists($from)) {return false;}
	$dir = opendir($from);
	while (false !== ($file = readdir($dir))) {
		if ($file == '.' OR $file == '..') {continue;}
		
		if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
			unlink_r($from . DIRECTORY_SEPARATOR . $file);
		}
		else {
			unlink($from . DIRECTORY_SEPARATOR . $file);
		}
	}
	rmdir($from);
	closedir($dir);
	return true;
}

Solution 25 - Php

What about this?

function Delete_Directory($Dir) 
{
  if(is_dir($Dir))
  {
      $files = glob( $Dir . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned
    
      foreach( $files as $file )
      {
          Delete_Directory( $file );      
      }
      if(file_exists($Dir))
      {
          rmdir($Dir);
      }
  } 
  elseif(is_file($Dir)) 
  {
     unlink( $Dir );  
  }
}

Refrence: https://paulund.co.uk/php-delete-directory-and-files-in-directory

Solution 26 - Php

You could copy the YII helpers

$directory (string) - to be deleted recursively.

$options (array) - for the directory removal. Valid options are: traverseSymlinks: boolean, whether symlinks to the directories should be traversed too. Defaults to false, meaning that the content of the symlinked directory would not be deleted. Only symlink would be removed in that default case.

public static function removeDirectory($directory,$options=array())
{
    if(!isset($options['traverseSymlinks']))
        $options['traverseSymlinks']=false;
    $items=glob($directory.DIRECTORY_SEPARATOR.'{,.}*',GLOB_MARK | GLOB_BRACE);
    foreach($items as $item)
    {
        if(basename($item)=='.' || basename($item)=='..')
            continue;
        if(substr($item,-1)==DIRECTORY_SEPARATOR)
        {
            if(!$options['traverseSymlinks'] && is_link(rtrim($item,DIRECTORY_SEPARATOR)))
                unlink(rtrim($item,DIRECTORY_SEPARATOR));
            else
                self::removeDirectory($item,$options);
        }
        else
            unlink($item);
    }
    if(is_dir($directory=rtrim($directory,'\\/')))
    {
        if(is_link($directory))
            unlink($directory);
        else
            rmdir($directory);
    }
}

Solution 27 - Php

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

Have your tryed out the obove code from php.net

Work for me fine

Solution 28 - Php

For windows:

system("rmdir ".escapeshellarg($path) . " /s /q");

Solution 29 - Php

Like Playnox's solution, but with the elegant built-in DirectoryIterator:

function delete_directory($dirPath){
 if(is_dir($dirPath)){
  $objects=new DirectoryIterator($dirPath);
   foreach ($objects as $object){
	if(!$object->isDot()){
	 if($object->isDir()){
	  delete_directory($object->getPathname());
	 }else{
      unlink($object->getPathname());
	 }
    }
   }
   rmdir($dirPath);
  }else{
   throw new Exception(__FUNCTION__.'(dirPath): dirPath is not a directory!');
  }
 }

Solution 30 - Php

I do not remember from where I copied this function, but it looks like it is not listed and it is working for me

function rm_rf($path) {
	if (@is_dir($path) && is_writable($path)) {
		$dp = opendir($path);
		while ($ent = readdir($dp)) {
			if ($ent == '.' || $ent == '..') {
				continue;
			}
			$file = $path . DIRECTORY_SEPARATOR . $ent;
			if (@is_dir($file)) {
				rm_rf($file);
			} elseif (is_writable($file)) {
				unlink($file);
			} else {
				echo $file . "is not writable and cannot be removed. Please fix the permission or select a new path.\n";
			}
		}
		closedir($dp);
		return rmdir($path);
	} else {
		return @unlink($path);
	}
}

Solution 31 - Php

Simple and Easy...

$dir ='pathtodir';
if (is_dir($dir)) {
  foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if ($filename->isDir()) continue;
    unlink($filename);
  }
  rmdir($dir);
}

Solution 32 - Php

If you are not sure, Given path is directory or file then you can use this function to delete path

function deletePath($path) {
        if(is_file($path)){
            unlink($path);
        } elseif(is_dir($path)){
            $path = (substr($path, -1) !== DIRECTORY_SEPARATOR) ? $path . DIRECTORY_SEPARATOR : $path;
            $files = glob($path . '*');
            foreach ($files as $file) {
                deleteDirPath($file);
            }
            rmdir($path);
        } else {
            return false;
        }
}

Solution 33 - Php

Here is a simple solution

$dirname = $_POST['d'];
    $folder_handler = dir($dirname);
    while ($file = $folder_handler->read()) {
        if ($file == "." || $file == "..")
            continue;
        unlink($dirname.'/'.$file);
        
    }
   $folder_handler->close();
   rmdir($dirname);

Solution 34 - Php

Platform independent code.

Took the answer from PHP.net

if(PHP_OS === 'Windows')
{
 exec("rd /s /q {$path}");
}
else
{
 exec("rm -rf {$path}");
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmattView Question on Stackoverflow
Solution 1 - PhpalcuadradoView Answer on Stackoverflow
Solution 2 - Phpuser3033886View Answer on Stackoverflow
Solution 3 - PhpYour Common SenseView Answer on Stackoverflow
Solution 4 - PhpBlaiseView Answer on Stackoverflow
Solution 5 - PhpGerman LatorreView Answer on Stackoverflow
Solution 6 - PhpGras DoubleView Answer on Stackoverflow
Solution 7 - PhpPlaynoxView Answer on Stackoverflow
Solution 8 - PhpBablu AhmedView Answer on Stackoverflow
Solution 9 - PhpWebTigersView Answer on Stackoverflow
Solution 10 - PhpTommzView Answer on Stackoverflow
Solution 11 - PhpChristopher SmitView Answer on Stackoverflow
Solution 12 - Phprealmag777View Answer on Stackoverflow
Solution 13 - PhpT.ToduaView Answer on Stackoverflow
Solution 14 - PhpadrianView Answer on Stackoverflow
Solution 15 - PhpcandlejackView Answer on Stackoverflow
Solution 16 - Phpuser701152View Answer on Stackoverflow
Solution 17 - PhpMatt ConnollyView Answer on Stackoverflow
Solution 18 - Phpkarma_policeView Answer on Stackoverflow
Solution 19 - PhpAlan TrewarthaView Answer on Stackoverflow
Solution 20 - PhpK-GunView Answer on Stackoverflow
Solution 21 - PhpAdeel Ahmed BalochView Answer on Stackoverflow
Solution 22 - PhpPP2000View Answer on Stackoverflow
Solution 23 - PhpPhil MeadowsView Answer on Stackoverflow
Solution 24 - PhpTarikView Answer on Stackoverflow
Solution 25 - PhpMohamad HamoudayView Answer on Stackoverflow
Solution 26 - PhpJosé VeríssimoView Answer on Stackoverflow
Solution 27 - PhpGaurangView Answer on Stackoverflow
Solution 28 - PhpMyloView Answer on Stackoverflow
Solution 29 - PhpMatthew SlymanView Answer on Stackoverflow
Solution 30 - PhpdavView Answer on Stackoverflow
Solution 31 - PhpNewtronView Answer on Stackoverflow
Solution 32 - Phpjay padaliyaView Answer on Stackoverflow
Solution 33 - PhpmajoView Answer on Stackoverflow
Solution 34 - PhpmysticmoView Answer on Stackoverflow