Delete directory with files in it?

2019-01-01 12:11发布

问题:

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.

回答1:

There are at least two options available nowdays.

  1. Before deleting the folder, delete all it\'s 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 needing to do 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);
    


回答2:

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

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

And then you can do

rmdir($dirname);


回答3:

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

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


回答4:

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


回答5:

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


回答6:

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


回答7:

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


回答8:

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: Copy entire contents of a directory to another using php



回答9:

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


回答10:

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


回答11:

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


回答12:

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


回答13:

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!!)



回答14:

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


回答15:

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


回答16:

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)



回答17:

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()


回答18:

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


回答19:

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


回答20:

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


回答21:

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


回答22:

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



回答23:

For windows:

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


回答24:

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!\');
  }
 }


回答25:

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


回答26:

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


回答27:

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



回答28:

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



回答29:

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


回答30:

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


标签: php rmdir