如何在 PHP 中递归删除目录及其全部内容(文件 + 子目录)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3338123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:23:33  来源:igfitidea点击:

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

phprecursiondelete-directory

提问by Itay Moav -Malimovka

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

如何在 PHP 中删除目录及其全部内容(文件和子目录)?

回答by Artefacto

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

手册页中的用户贡献部分rmdir包含一个不错的实现:

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

回答by salathe

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

基于The Pixel Developer 的评论,使用 SPL 的片段可能如下所示:

$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 nosanity checking and makes use of the SKIP_DOTS flag introduced with the FilesystemIterator in PHP 5.3.0. Of course, the $todocould be an if/else. The important point is that CHILD_FIRSTis used to iterate over the children (files) first before their parent (folders).

注:它确实没有完整性检查,并利用在PHP 5.3.0与FilesystemIterator推出SKIP_DOTS标志。当然,$todo可以是if/ else。重要的一点是CHILD_FIRST用于在其父级(文件夹)之前首先迭代子级(文件)。

回答by Liko

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")) ? recurseRmdir("$dir/$file") : unlink("$dir/$file");
  }
  return rmdir($dir);
}

回答by ankitjaininfo

For *nix you can use a shell_execfor rm -Ror DEL /S folder_namefor Windows.

对于 *nix,您可以使用shell_execforrm -RDEL /S folder_namefor Windows。

回答by XzaR

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

回答by David Newcomb

There is another thread with more examples here: A recursive remove directory function for PHP?

这里还有另一个包含更多示例的线程: A recursive remove directory function for PHP?

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

如果你使用 Yii,那么你可以把它留给框架:

CFileHelper::removeDirectory($my_directory);

回答by Programster

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

“简单”的代码可以工作并且可以被 10 岁的孩子阅读:

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: In PHP how do I recursively remove all folders that aren't empty?

请注意,我所做的只是扩展/简化和修复(不适用于非空目录)这里的解决方案: 在 PHP 中,我如何递归删除所有非空文件夹?

回答by jave.web

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

增强了@Arteacto 的解决方案 - 更正了拼写错误并简化了代码,适用于两者 - 空 && 非空目录。

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

回答by David Pankov

The 100% working solution

100% 有效的解决方案

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

回答by jlh

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($path) {
    if (is_dir($path)) {
        foreach (scandir($path) as $entry) {
            if (!in_array($entry, ['.', '..'])) {
                recursiveRemove($path . DIRECTORY_SEPARATOR . $entry);
            }
        }
        rmdir($path);
    } else {
        unlink($path);
    }
}