How do I recursively delete a directory and its entire contents (files + sub dirs) in PHP?

PhpRecursionDelete Directory

Php Problem Overview


How do I delete a directory and its entire contents (files and subdirectories) in PHP?

Php Solutions


Solution 1 - Php

The user-contributed section in the manual page of rmdir contains a decent implementation:

 function rrmdir($dir) { 
   if (is_dir($dir)) { 
     $objects = scandir($dir);
     foreach ($objects as $object) { 
       if ($object != "." && $object != "..") { 
         if (is_dir($dir. DIRECTORY_SEPARATOR .$object) && !is_link($dir."/".$object))
           rrmdir($dir. DIRECTORY_SEPARATOR .$object);
         else
           unlink($dir. DIRECTORY_SEPARATOR .$object); 
       } 
     }
     rmdir($dir); 
   } 
 }

Solution 2 - Php

Building on The Pixel Developer's comment, a snippet using the SPL might look like:

$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
    RecursiveIteratorIterator::CHILD_FIRST
);

foreach ($files as $fileinfo) {
    $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
    $todo($fileinfo->getRealPath());
}

rmdir($dir);

Note: It does no sanity checking and makes use of the SKIP_DOTS flag introduced with the FilesystemIterator in PHP 5.3.0. Of course, the $todo could be an if/else. The important point is that CHILD_FIRST is used to iterate over the children (files) first before their parent (folders).

Solution 3 - Php

Deletes all files and folders in the path.

function recurseRmdir($dir) {
  $files = array_diff(scandir($dir), array('.','..'));
  foreach ($files as $file) {
    (is_dir("$dir/$file") && !is_link("$dir/$file")) ? recurseRmdir("$dir/$file") : unlink("$dir/$file");
  }
  return rmdir($dir);
}

Solution 4 - Php

For *nix you can use a shell_exec for rm -R or DEL /S folder_name for Windows.

Solution 5 - Php

There is another thread with more examples here: https://stackoverflow.com/questions/1407338/a-recursive-remove-directory-function-for-php

If you are using Yii then you can leave it to the framework:

CFileHelper::removeDirectory($my_directory);

Solution 6 - Php

<?php

use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;

# http://stackoverflow.com/a/3352564/283851
# https://gist.github.com/XzaR90/48c6b615be12fa765898

# Forked from https://gist.github.com/mindplay-dk/a4aad91f5a4f1283a5e2

/**
 * Recursively delete a directory and all of it's contents - e.g.the equivalent of `rm -r` on the command-line.
 * Consistent with `rmdir()` and `unlink()`, an E_WARNING level error will be generated on failure.
 *
 * @param string $source absolute path to directory or file to delete.
 * @param bool 	 $removeOnlyChildren set to true will only remove content inside directory.
 *
 * @return bool true on success; false on failure
 */
function rrmdir($source, $removeOnlyChildren = false)
{
	if(empty($source) || file_exists($source) === false)
	{
		return false;
	}
	
	if(is_file($source) || is_link($source))
	{
	    return unlink($source);
	}
	
	$files = new RecursiveIteratorIterator
	(
		new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
		RecursiveIteratorIterator::CHILD_FIRST
	);

    //$fileinfo as SplFileInfo
	foreach($files as $fileinfo)
	{
		if($fileinfo->isDir())
		{
			if(rrmdir($fileinfo->getRealPath()) === false)
			{
				return false;
			}
		}
		else
		{
			if(unlink($fileinfo->getRealPath()) === false)
			{
				return false;
			}
		}
	}
	
	if($removeOnlyChildren === false)
	{
		return rmdir($source);
	}
	
	return true;
}

Solution 7 - Php

The 100% working solution

public static function rmdir_recursive($directory, $delete_parent = null)
  {
    $files = glob($directory . '/{,.}[!.,!..]*',GLOB_MARK|GLOB_BRACE);
    foreach ($files as $file) {
      if (is_dir($file)) {
        self::rmdir_recursive($file, 1);
      } else {
        unlink($file);
      }
    }
    if ($delete_parent) {
      rmdir($directory);
    }
  }

Solution 8 - Php

It seems that all other answers assume the path given to the function is always a directory. This variant works to remove directories as well as single files:

/**
 * Recursively delete a file or directory.  Use with care!
 *
 * @param string $path
 */
function recursiveRemove(string $path) {
    if (is_dir($path)) {
        foreach (scandir($path) as $entry) {
            if (!in_array($entry, ['.', '..'], true)) {
                recursiveRemove($path . DIRECTORY_SEPARATOR . $entry);
            }
        }
        rmdir($path);
    } else {
        unlink($path);
    }
}

EDIT: If you're picky (and you should be picky) you may want to add code to check for scandir(), rmdir() and unlink() returning an error and throw an exception if so.

Solution 9 - Php

Using DirectoryIterator and recursion correctly:

function deleteFilesThenSelf($folder) {
    foreach(new DirectoryIterator($folder) as $f) {
        if($f->isDot()) continue; // skip . and ..
        if ($f->isFile()) {
    		unlink($f->getPathname());
    	} else if($f->isDir()) {
    	    deleteFilesThenSelf($f->getPathname());
    	}
    }
    rmdir($folder);
}

Solution 10 - Php

'simple' code that works and can be read by a ten year old:

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

Please note that all I did was expand/simplify and fix (didn't work for non empty dir) the solution here: https://stackoverflow.com/questions/9760526/php-remove-not-empty-folder

Solution 11 - Php

Example with glob() function. It will delete all files and folders recursively, including files that starts with dot.

delete_all( 'folder' );

function delete_all( $item ) {
	if ( is_dir( $item ) ) {
		array_map( 'delete_all', array_diff( glob( "$item/{,.}*", GLOB_BRACE ), array( "$item/.", "$item/.." ) ) );
		rmdir( $item );
	} else {
		unlink( $item );
	}
};

Solution 12 - Php

Enhanced @Artefacto 's solution - corrected typos and simplified code, working for both - empty && non-empty directories .

  function recursive_rmdir($dir) { 
    if( is_dir($dir) ) { 
      $objects = array_diff( scandir($dir), array('..', '.') );
      foreach ($objects as $object) { 
        $objectPath = $dir."/".$object;
        if( is_dir($objectPath) )
          recursive_rmdir($objectPath);
        else
          unlink($objectPath); 
      } 
      rmdir($dir); 
    } 
  }

Solution 13 - 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 14 - Php

unlinkr function recursively deletes all the folders and files in given path by making sure it doesn't delete the script itself.

function unlinkr($dir, $pattern = "*") {
    // find all files and folders matching pattern
    $files = glob($dir . "/$pattern"); 

    //interate thorugh the files and folders
    foreach($files as $file){ 
    //if it is a directory then re-call unlinkr function to delete files inside this directory     
        if (is_dir($file) and !in_array($file, array('..', '.')))  {
            echo "<p>opening directory $file </p>";
            unlinkr($file, $pattern);
            //remove the directory itself
            echo "<p> deleting directory $file </p>";
            rmdir($file);
        } else if(is_file($file) and ($file != __FILE__)) {
            // make sure you don't delete the current script
            echo "<p>deleting file $file </p>";
            unlink($file); 
        }
    }
}

if you want to delete all files and folders where you place this script then call it as following

//get current working directory
$dir = getcwd();
unlinkr($dir);

if you want to just delete just php files then call it as following

unlinkr($dir, "*.php");

you can use any other path to delete the files as well

unlinkr("/home/user/temp");

This will delete all files in home/user/temp directory.

Solution 15 - Php

I use this code ...

 function rmDirectory($dir) {
        foreach(glob($dir . '/*') as $file) {
            if(is_dir($file))
                rrmdir($file);
            else
                unlink($file);
        }
        rmdir($dir);
    }

or this one...

<?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

Once you finish running tests , just remove # from the #unlink and #rmdir in the class .

<?php 
class RMRFiles {

        function __construct(){
        }

	public function recScan( $mainDir, $allData = array() )
	{
	
	// hide files
	$hidefiles = array(
	".",
	"..") ;
	
	//start reading directory
	$dirContent = scandir( $mainDir ) ;
		
		//cycle through
		foreach ( $dirContent as $key => $content )
		{
			$path = $mainDir . '/' . $content ;
			
			// if is readable / file
			if ( ! in_array( $content, $hidefiles ) )
			{
			if ( is_file( $path ) && is_readable( $path ) )
			{
			#delete files within directory
			#unlink($path);
			$allData['unlink'][] = $path ;
			}
			
			// if is readable / directory
			else
			if ( is_dir( $path ) && is_readable( $path ) )
			{
			/*recursive*/
			$allData = $this->recScan( $path, $allData ) ;
			
			#finally remove directory
			$allData['rmdir'][]=$path;
			#rmdir($path);
			}
			}
		}
	
	return $allData ;
	
	}
	
}

header("Content-Type: text/plain");

/* Get absolute path of the running script 
Ex : /home/user/public_html/   */
define('ABPATH', dirname(__file__) . '/'); 

/* The folder where we store cache files 
Ex: /home/user/public_html/var/cache   */
define('STOREDIR','var/cache'); 

$rmrf = new RMRFiles();
#here we delete folder content files & directories
print_r($rmrf->recScan(ABPATH.STOREDIR));
#finally delete scanned directory ? 
#rmdir(ABPATH.STOREDIR);

?>

Solution 17 - Php

<?php

/**
 * code by Nk (nk.have.a@gmail.com)
 */

class filesystem
{
	public static function remove($path)
	{
		return is_dir($path) ? rmdir($path) : unlink($path);
	}

	public static function normalizePath($path)
	{
		return $path.(is_dir($path) && !preg_match('@/$@', $path) ? '/' : '');		
	}

	public static function rscandir($dir, $sort = SCANDIR_SORT_ASCENDING)
	{
		$results = array();

		if(!is_dir($dir))
		return $results;

		$dir = self::normalizePath($dir);

		$objects = scandir($dir, $sort);

		foreach($objects as $object)
		if($object != '.' && $object != '..')
		{
			if(is_dir($dir.$object))
			$results = array_merge($results, self::rscandir($dir.$object, $sort));
			else
			array_push($results, $dir.$object);
		}

		array_push($results, $dir);

		return $results;
	}

	public static function rrmdir($dir)
	{
		$files = self::rscandir($dir);

		foreach($files as $file)
		self::remove($file);

		return !file_exists($dir);
	}
}

?>

cleanup.php :

<?php

/* include.. */

filesystem::rrmdir('/var/log');
filesystem::rrmdir('./cache');

?>

Solution 18 - Php

I juste made this code, from some StackOverflow discussions. I didn't test on Linux environment yet. It is made in order to delete a file or a directory, completely :

function splRm(SplFileInfo $i)
{
    $path = $i->getRealPath();

    if ($i->isDir()) {
        echo 'D - ' . $path . '<br />';
        rmdir($path);
    } elseif($i->isFile()) {
        echo 'F - ' . $path . '<br />';
        unlink($path);
    }
}

function splRrm(SplFileInfo $j)
{
    $path = $j->getRealPath();

    if ($j->isDir()) {
        $rdi = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
        $rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($rii as $i) {
            splRm($i);
        }
    }
    splRm($j);

}

splRrm(new SplFileInfo(__DIR__.'/../dirOrFileName'));

Solution 19 - Php

function rmdir_recursive( $dirname ) {

	/**
	 * FilesystemIterator and SKIP_DOTS
	 */

	if ( class_exists( 'FilesystemIterator' ) && defined( 'FilesystemIterator::SKIP_DOTS' ) ) {

		if ( !is_dir( $dirname ) ) {
			return false;
		}

		foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) {
			$path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() );
		}

		return rmdir( $dirname );

	}

	/**
	 * RecursiveDirectoryIterator and SKIP_DOTS
	 */

	if ( class_exists( 'RecursiveDirectoryIterator' ) && defined( 'RecursiveDirectoryIterator::SKIP_DOTS' ) ) {

		if ( !is_dir( $dirname ) ) {
			return false;
		}

		foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname, RecursiveDirectoryIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) {
			$path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() );
		}

		return rmdir( $dirname );

	}

	/**
	 * RecursiveIteratorIterator and RecursiveDirectoryIterator
	 */

	if ( class_exists( 'RecursiveIteratorIterator' ) && class_exists( 'RecursiveDirectoryIterator' ) ) {

		if ( !is_dir( $dirname ) ) {
			return false;
		}

		foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) {
			if ( in_array( $path->getFilename(), array( '.', '..' ) ) ) {
				continue;
			}
			$path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() );
		}

		return rmdir( $dirname );

	}

	/**
	 * Scandir Recursive
	 */

	if ( !is_dir( $dirname ) ) {
		return false;
	}

	$objects = scandir( $dirname );

	foreach ( $objects as $object ) {
		if ( $object === '.' || $object === '..' ) {
			continue;
		}
		filetype( $dirname . DIRECTORY_SEPARATOR . $object ) === 'dir' ? rmdir_recursive( $dirname . DIRECTORY_SEPARATOR . $object ) : unlink( $dirname . DIRECTORY_SEPARATOR . $object );
	}

	reset( $objects );
	rmdir( $dirname );

	return !is_dir( $dirname );

}

Solution 20 - Php

Modified variant of @XzaR solution. It does remove empty folders, when all files are deleted from them and it throws exceptions instead of returning false on errors.

function recursivelyRemoveDirectory($source, $removeOnlyChildren = true)
{
    if (empty($source) || file_exists($source) === false) {
        throw new Exception("File does not exist: '$source'");
    }

    if (is_file($source) || is_link($source)) {
        if (false === unlink($source)) {
            throw new Exception("Cannot delete file '$source'");
        }
    }

    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );

    foreach ($files as $fileInfo) {
        /** @var SplFileInfo $fileInfo */
        if ($fileInfo->isDir()) {
            if ($this->recursivelyRemoveDirectory($fileInfo->getRealPath()) === false) {
                throw new Exception("Failed to remove directory '{$fileInfo->getRealPath()}'");
            }
            if (false === rmdir($fileInfo->getRealPath())) {
                throw new Exception("Failed to remove empty directory '{$fileInfo->getRealPath()}'");
            }
        } else {
            if (unlink($fileInfo->getRealPath()) === false) {
                throw new Exception("Failed to remove file '{$fileInfo->getRealPath()}'");
            }
        }
    }

    if ($removeOnlyChildren === false) {
        if (false === rmdir($source)) {
            throw new Exception("Cannot remove directory '$source'");
        }
    }
}

Solution 21 - Php

function deltree_cat($folder)
{
	if (is_dir($folder))
	{
			 $handle = opendir($folder);
			 while ($subfile = readdir($handle))
			 {
					 if ($subfile == '.' or $subfile == '..') continue;
					 if (is_file($subfile)) unlink("{$folder}/{$subfile}");
					 else deltree_cat("{$folder}/{$subfile}");
			 }
			 closedir($handle);
			 rmdir ($folder);
	 }
	 else
	 {
		unlink($folder);
	 }
}

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
QuestionItay Moav -MalimovkaView Question on Stackoverflow
Solution 1 - PhpArtefactoView Answer on Stackoverflow
Solution 2 - PhpsalatheView Answer on Stackoverflow
Solution 3 - PhpLikoView Answer on Stackoverflow
Solution 4 - PhpankitjaininfoView Answer on Stackoverflow
Solution 5 - PhpDavid NewcombView Answer on Stackoverflow
Solution 6 - PhpXzaRView Answer on Stackoverflow
Solution 7 - PhpDavid PankovView Answer on Stackoverflow
Solution 8 - PhpjlhView Answer on Stackoverflow
Solution 9 - PhpAvaLanCSView Answer on Stackoverflow
Solution 10 - PhpProgramsterView Answer on Stackoverflow
Solution 11 - PhpDanijelView Answer on Stackoverflow
Solution 12 - Phpjave.webView Answer on Stackoverflow
Solution 13 - PhpK-GunView Answer on Stackoverflow
Solution 14 - PhpTofeeqView Answer on Stackoverflow
Solution 15 - PhpHamedView Answer on Stackoverflow
Solution 16 - PhpAlin RazvanView Answer on Stackoverflow
Solution 17 - PhpNkcView Answer on Stackoverflow
Solution 18 - PhpChicnaView Answer on Stackoverflow
Solution 19 - PhpD3F4ULTView Answer on Stackoverflow
Solution 20 - PhpVladislav RastrusnyView Answer on Stackoverflow
Solution 21 - PhpIlya YaremchukView Answer on Stackoverflow