PHP: 删除目录中的所有文件,然后删除该目录

34
有没有办法在PHP中使用RegExp通配符搜索来快速删除文件夹内的所有文件,然后删除该文件夹,而不使用"exec"命令?我的服务器不允许我使用该命令。一个简单的循环就足够了。
我需要的是能够实现以下语句逻辑的方法,但显然是有效的:
$dir = "/home/dir"
unlink($dir . "/*"); # "*" being a match for all strings
rmdir($dir);

https://dev59.com/yHA75IYBdhLWcg3wVneI - John
https://dev59.com/UnA75IYBdhLWcg3wW3sZ - Jocelyn
9个回答

84
使用glob函数来查找与模式匹配的所有文件。
function recursiveRemoveDirectory($directory)
{
    foreach(glob("{$directory}/*") as $file)
    {
        if(is_dir($file)) { 
            recursiveRemoveDirectory($file);
        } else {
            unlink($file);
        }
    }
    rmdir($directory);
}

3
我收到了一个错误信息:达到了100层的最大函数嵌套级别 - Smith
我在我的代码中使用scandir函数时遇到了权限问题,现在使用这个版本它完美地工作了! - SeinopSys
2
glob 处理隐藏文件吗? - amar
超棒的解决方案 :D - FosAvance
1
使用} else if(!is_link($file)) {而不是仅仅使用} else {,以确保符号链接的安全。 - jla
小心处理glob和大量文件。在某些条件下,它可能会消耗大量内存并导致性能问题。 - Taras

18
使用glob()函数可以轻松遍历目录并删除文件,然后您可以删除该目录。
foreach (glob($dir."/*.*") as $filename) {
    if (is_file($filename)) {
        unlink($filename);
    }
}
rmdir($dir);

16
这段代码存在危险性,应该在 glob 函数中包含路径,例如 glob($dir."/*.*")。我曾经尝试过这样做,结果把整个目录都清空了,包括顶部的文件夹,我的工作也被清空了。 - Smith

10

glob() 函数可以实现你所需的功能。如果你使用的是 PHP 5.3 或以上版本,你可以像这样做:

$dir = ...
array_walk(glob($dir . '/*'), function ($fn) {
    if (is_file($fn))
        unlink($fn);
});
unlink($dir);

8

使用标准PHP库,特别是RecursiveIteratorIteratorRecursiveDirectoryIterator递归删除所有文件和文件夹的简单有效方法。重点在于RecursiveIteratorIterator::CHILD_FIRST标志,迭代器将首先循环遍历文件,最后是目录,因此一旦目录为空,就可以安全地使用rmdir()

foreach( new RecursiveIteratorIterator( 
    new RecursiveDirectoryIterator( 'folder', FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS ), 
    RecursiveIteratorIterator::CHILD_FIRST ) as $value ) {
        $value->isFile() ? unlink( $value ) : rmdir( $value );
}

rmdir( 'folder' );

这是一个美丽的回答,几乎是10年前的...我喜欢PHP中的RecursiveIteratorIterator和RecursiveDirectoryIterator的实现,因为它们不仅标准和安全,而且快速和干净。这应该是每个人都使用的答案!这是一个美丽的回答,几乎是10年前的...我喜欢PHP中的RecursiveIteratorIterator和RecursiveDirectoryIterator的实现,因为它们不仅标准和安全,而且快速和干净。这应该是每个人都使用的答案! - Julio Marchi

6

尝试简单的方法:

$dir = "/home/dir";
array_map('unlink', glob($dir."/*"));
rmdir($dir);

在删除目录的函数中:

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('..', '.')))  {
                unlinkr($file, $pattern);
                //remove the directory itself
                rmdir($file);
                } else if(is_file($file) and ($file != __FILE__)) {
                // make sure you don't delete the current script
                unlink($file); 
            }
        }
        rmdir($dir);
    }

//call following way:
unlinkr("/home/dir");

2
虽然这段代码片段可能解决了问题,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议的原因。 - Bono

4
您可以使用Symfony Filesystem 组件来避免重复造轮子,以此达到您所需的功能。
use Symfony\Component\Filesystem\Filesystem;

$filesystem = new Filesystem();

if ($filesystem->exists('/home/dir')) {
    $filesystem->remove('/home/dir');
}

如果您想自己管理代码,这里是有关方法的Symfony代码库。
class MyFilesystem
{
    private function toIterator($files)
    {
        if (!$files instanceof \Traversable) {
            $files = new \ArrayObject(is_array($files) ? $files : array($files));
        }

        return $files;
    }

    public function remove($files)
    {
        $files = iterator_to_array($this->toIterator($files));
        $files = array_reverse($files);
        foreach ($files as $file) {
            if (!file_exists($file) && !is_link($file)) {
                continue;
            }

            if (is_dir($file) && !is_link($file)) {
                $this->remove(new \FilesystemIterator($file));

                if (true !== @rmdir($file)) {
                    throw new \Exception(sprintf('Failed to remove directory "%s".', $file), 0, null, $file);
                }
            } else {
                // https://bugs.php.net/bug.php?id=52176
                if ('\\' === DIRECTORY_SEPARATOR && is_dir($file)) {
                    if (true !== @rmdir($file)) {
                        throw new \Exception(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                } else {
                    if (true !== @unlink($file)) {
                        throw new \Exception(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                }
            }
        }
    }

    public function exists($files)
    {
        foreach ($this->toIterator($files) as $file) {
            if (!file_exists($file)) {
                return false;
            }
        }

        return true;
    }
}

1

其中一种方法是:

function unlinker($file)
{
    unlink($file);
}
$files = glob('*.*');
array_walk($files,'unlinker');
rmdir($dir);

0

如果要删除所有文件,您可以删除该目录并再次创建..只需一行简单的代码

<?php 
    $dir = '/home/files/';
    rmdir($dir);
    mkdir($dir);
?>

0
不需要先创建一个数组,肯定更快。有时候需要特殊处理,才能删除一个文件夹。
function clean_dir($dir){
        $error='';
        $dh=opendir($dir);
        while($dh&&($file=readdir($dh))!=false){
            if($file=='.'||$file=='..')continue;
            $rp=$dir=='.'?$file:"$dir/$file";
            if(!is_readable($rp)){$error.=PHP_EOL.$rp;continue;}
            if(is_link($rp))@unlink(readlink($rp));
            elseif(is_file($rp))
            chmod($rp,octdec(644))!=false?@unlink($rp):$error.=PHP_EOL.$rp;
            elseif(is_dir($rp)){
                if(chmod($rp,octdec(755))!=false)
                    count(scandir($rp))==2?@rmdir($rp):clean_dir($rp);
                else{$error.=PHP_EOL.$rp;}
            }
        }
        closedir($dh);
        return($error);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接