【问题标题】:PHP unlink() Error: "Directory not empty"PHP unlink() 错误:“目录不为空”
【发布时间】:2017-06-12 09:37:39
【问题描述】:

我有以下递归方法来删除一个目录及其所有子目录和文件:

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

有时会收到警告,“目录不为空”

该目录实际上是作为文件的临时持有者创建的。这些文件是使用以下 sn-p 从 Internet 下载的:

file_put_contents($filename, file_get_contents($file))

下载后(写入操作),然后将其上传到网站(读取操作)。上传完成后,临时文件夹及其文件将被删除。

奇怪的是,当我查看临时文件夹时,那里没有文件。好像代码在最后一个文件正在被删除的过程中试图删除文件夹?

任何想法可能是错误的以及如何解决它?我需要此代码在 Windows 和 *nix 上运行,因此不能选择仅 *nix 的解决方案。

【问题讨论】:

  • 目录中是否存在“dotfiles”? (如果不允许 php 用户查看它们,这些命令可能不会显示在列表命令中)。类似的适用于隐藏文件和 .db 文件的窗口。当您尝试删除这些文件时,它们也可能正在被使用以防止它们被删除,但我怀疑这会引发错误或警告。
  • 没有“点文件”。下载到该文件夹​​的文件是图像(主要是 JPG)。创建这些文件夹只是为了作为这些图像的临时容器。文件夹中没有其他任何操作。
  • 尝试将行 if (filetype($dir . '/' . $object) == 'dir') { 更改为 if (is_dir($dir . '/' . $object)) {,就像您在方法开始时所做的那样。

标签: php


【解决方案1】:

常量 DIRECTORY_SEPARATOR 可能会帮助您实现 Windows/Unix 兼容性。 对于不为空的文件夹,请尝试以下操作:

protected function _rrmdir($dir)
{
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != '.' && $object != '..') {
                if (is_dir($dir . DIRECTORY_SEPARATOR . $object)) {
                    _rrmdir($dir . DIRECTORY_SEPARATOR . $object);
                } else {
                    if( is_file($dir . DIRECTORY_SEPARATOR . $object) ) {
                        if(!unlink($dir . DIRECTORY_SEPARATOR . $object)) {
                            // code in case the file was not removed
                        }
                        // wait a bit here?
                    } else {
                        // code for debug file permission issues
                    }
                }
            }
        }
        reset($objects);
        rmdir($dir);
    }
}

您可能会尝试删除权限不在 php exec 级别的文件。
is_file() 方法将仅在没有读取权限时返回 FALSE,请注意执行所有者需要写入权限才能删除文件。

【讨论】:

  • 测试你的代码。请记住,问题是非常间歇性的。感谢您建议使用DIRECTORY_SEPARATORis_file()
  • 我仍然间歇性地遇到问题(文件夹没有被删除)。现在不同的是,我不再收到关于 Directory Not Empty 的警告。一定是 rmdir() 的问题?
  • mmm... 动作间歇性,这可能是由于递归堆栈有时会在操作系统实际删除文件夹中的“最后一个文件”之前为空,然后,当执行堆栈到达(父文件夹),操作系统没有释放导致警告的文件的链接。你在哪个操作系统上工作?如果这是真的,可能会得到像 $result=unlink(...) 这样的 unlink 响应,或者在 unlink 命令之后稍微休眠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 2014-07-20
  • 1970-01-01
  • 2020-08-20
  • 2017-10-29
相关资源
最近更新 更多