删除包含文件的目录?

mat*_*att 226 php rmdir

我想知道,删除目录中包含所有文件的最简单方法是什么?

我正在使用rmdir(PATH . '/' . $value);删除文件夹,但是,如果其中有文件,我根本无法删除它.

alc*_*ado 351

现在至少有两种选择.

  1. 在删除文件夹之前,删除它的所有文件和文件夹(这意味着递归!).这是一个例子:

    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);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果你使用的是5.2+,你可以使用RecursiveIterator来完成它而不需要自己进行递归:

    $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);
    
    Run Code Online (Sandbox Code Playgroud)

  • 在构建发送_to_ os的路径时,不需要DIRECTORY_SEPARATOR.Windows也会接受正斜杠.它主要用于`explode()`从操作系统中获取的路径.http://alanhogan.com/tips/php/directory-separator-not-necessary (25认同)
  • 你的第二个实现有点危险:它不检查点(`.`和`..`)并删除已解析的路径,而不是实际的路径. (11认同)
  • little add-on :-) glob()不支持像.htaccess这样的文件.我使用该函数清除由KCFinder(CKEditor插件)生成的目录,它生成.htaccess和.thumbs(文件+文件夹).相反,我使用`scandir`函数来获取文件夹列表.只需确保过滤'.' 和结果列表中的'..'文件. (9认同)
  • 除了@Alix Axel在这里使用[SplFileInfo :: getRealPath()](http://php.net/manual/en/splfileinfo.getrealpath.php)不是一个好主意.此方法扩展了所有符号链接,这意味着,将从某个位置删除实际文件,而不是从目标目录中删除符号链接.您应该使用SplFileInfo :: getPathname(). (4认同)
  • 我同意@Vijit,使用getPathname()而不是getRealPath()。如果找到符号链接,它所做的相同的事情不会删除比您期望的更多的内容。 (2认同)

use*_*886 184

我通常用它来删除文件夹中的所有文件:

array_map('unlink', glob("$dirname/*.*"));
Run Code Online (Sandbox Code Playgroud)

然后你就可以做到

rmdir($dirname);
Run Code Online (Sandbox Code Playgroud)

  • 这不会递归删除文件夹; 它只适用于文件夹中只有常规文件,所有文件都有文件扩展名. (25认同)
  • 为了从文件夹中删除*所有*文件,不仅是带有扩展名的文件,请按以下方式使用 glob:`array_map('unlink', glob("$dirname/*"));` 这仍然没有允许您删除嵌套在文件夹中的目录。 (5认同)
  • 如果不需要递归,那么到目前为止这是最好和最简单的答案.谢谢! (4认同)

You*_*nse 79

删除包含所有文件的目录的最简单方法是什么?

system("rm -rf ".escapeshellarg($dir));
Run Code Online (Sandbox Code Playgroud)

  • @与上述任何代码完全相同.不是吗? (103认同)
  • 我希望你不认真.如果$ dir是/会发生什么? (30认同)
  • 请注意,根据`$ dir`的生成/提供方式,您可能需要进行一些额外的预处理以确保安全并避免错误.例如,如果`$ dir`中可能有未转义的空格或分号,则可能会产生不良副作用.使用诸如`rmdir()`之类的答案不是这种情况,因为它会为你处理特殊字符. (7认同)
  • @ThePixelDeveloper如果您的PHP脚本有权删除根目录中的文件/文件夹,那么无论如何您都会遇到严重的问题。 (7认同)
  • Windows版本:`system('rmdir'.escapeshellarg($ path).'/ s/q');` (3认同)
  • @ThePixelDeveloper 您不必担心删除 /,这仅在您以 root 用户身份在命令行中运行脚本时才有效,因为在 web 中一切都以 apache 用户身份发生 (2认同)
  • @FluorescentGreen5 好的公平。让我们称之为利基解决方案。就个人而言,我无法想象 PHP 可以在 Linux 以外的任何操作系统上运行,而且我忘记了使用共享主机的时间。 (2认同)
  • 我比其他人更喜欢这个答案,唯一的问题是 Linux 依赖性,而对于安全问题,调用者的工作是检查它是否真的是预期的目录,该函数的唯一工作是*删除目录* . (2认同)

Bla*_*ise 48

完成工作的短功能:

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

我在这样的Utils类中使用它:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

强大的功能带来了很大的责任:当您使用空值调用此函数时,它将删除以root(/)开头的文件.作为安全措施,您可以检查路径是否为空:

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

  • 小心!此函数不检查路径是否确实存在.如果传递一个空参数,该函数将从root开始删除文件!在运行此功能之前,请在路径中添加健全性检查. (3认同)
  • 有些人没有看到Tatu的评论,而是递归删除了`/`,所以我在帖子中附加了受保护的版本。 (3认同)
  • 有人可以解释一行`array_map($ class_func,glob($ path.'/*'))== @rmdir($ path)`?我猜他正在通过子文件夹递归,但是== @rmdir部分做了什么?<array of booleans> == <boolean>如何返回答案?是否检查递归的每个返回值是否与右边的布尔值相同? (2认同)
  • 将两个语句合并为一个语句是一个技巧.这是因为三元运算符每个参数只允许一个语句.`array_map(...)`删除目录中的所有文件,`@rddir(...)`删除目录本身. (2认同)

Pla*_*nox 18

这是一个较短的版本对我很有用

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ger*_*rre 16

正如在PHP手册页上的大多数投票评论中所见rmdir()(参见http://php.net/manual/es/function.rmdir.php),glob()函数不会返回隐藏文件. scandir()提供作为解决该问题的替代方案.

那里描述的算法(在我的例子中就像魅力一样)是:

<?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); 
    } 
?>
Run Code Online (Sandbox Code Playgroud)


Gra*_*ble 13

您可以使用Symfony的文件系统(代码):

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

(new Filesystem)->remove($dir);
Run Code Online (Sandbox Code Playgroud)

但是我无法用这种方法删除一些复杂的目录结构,所以首先你应该尝试它以确保它正常工作.


我可以使用Windows特定的实现删除所述目录结构:

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


只是为了完整起见,这是我的旧代码:

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);
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*mmz 9

这里有一个简单的递归来删除源目录中的所有文件,包括该目录:

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

}
Run Code Online (Sandbox Code Playgroud)

函数基于复制目录的递归.你可以在这里找到这个功能: 使用php将目录的全部内容复制到另一个目录


T.T*_*dua 7

对我来说最好的解决方案

my_folder_delete("../path/folder");
Run Code Online (Sandbox Code Playgroud)

代码:

function my_folder_delete($path) {
    if (in_array($path, ['.', '/'])) return; // ensure to avoid accidents
    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);
    }
}
Run Code Online (Sandbox Code Playgroud)

PS记住!
不要将空值传递给任何目录删除功能!!!(始终备份它们,否则有一天您可能会遇到灾难!)


Bab*_*med 7

您可以尝试如下:

/*
 * 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*mit 6

这个对我有用:

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


Web*_*ers 6

我不敢相信有 30 多个答案。在 PHP 中递归删除文件夹可能需要几分钟时间,具体取决于目录的深度和其中的文件数量!你可以用一行代码来做到这一点......

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

如果您担心删除整个文件系统,请首先确保您的$dir路径正是您想要的。切勿允许用户输入可以直接删除文件的内容,而无需首先对输入进行大量验证。这是基本的编码实践。

  • 这!但我会做 `shell_exec("rm -rf '$dir'");` (2认同)

小智 5

对 alcuadrado 的代码进行了一点修改 -glob看不到具有名称的文件,例如.htaccess我使用 scandir 并且脚本删除自身 - 检查__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);
}
Run Code Online (Sandbox Code Playgroud)


can*_*ack 5

Glob 函数不会返回隐藏文件,因此当尝试递归删除树时, scandir 可能更有用。

<?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);
  }
?>
Run Code Online (Sandbox Code Playgroud)


rea*_*777 5

Linux服务器示例: exec('rm -f -r ' . $cache_folder . '/*');