PHP删除空目录报错:Warning: rmdir(): Directory not empty问题排查
解决rmdir(): Directory not empty警告(空目录删除失败)
这个问题我之前也踩过坑!核心原因是你的glob匹配规则没覆盖到隐藏文件,导致你以为是空的目录里其实还有残留文件,最终触发了rmdir的警告。
问题根源
你代码里用的glob($target . '*', GLOB_MARK)只会匹配不以点(.)开头的普通文件/目录,但Linux/Unix系统里的隐藏文件(比如.htaccess、.gitignore)或者某些遗留的隐藏文件会被漏掉。这些文件留在目录里,就会让rmdir认为目录不为空,从而报错。
另外,glob默认也不会匹配.(当前目录)和..(上级目录),不过这两个不会影响删除,但我们处理的时候需要过滤掉,避免递归出错。
修复后的代码
public function delete_files($target) { // 标准化路径,确保末尾有目录分隔符,避免匹配错误 $target = rtrim($target, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; if (is_dir($target)) { // 使用GLOB_BRACE匹配普通文件和隐藏文件 $files = glob($target . '{,.}*', GLOB_BRACE | GLOB_MARK); foreach ($files as $file) { // 跳过当前目录(.)和上级目录(..) if ($file === $target . '.' || $file === $target . '..') { continue; } $this->delete_files($file); } // 尝试删除目录前,额外校验是否真的为空 if (count(glob($target . '{,.}*', GLOB_BRACE)) === 2) { // 只剩.和..两个项 rmdir($target); } else { $this->logger->error("Directory $target is not empty after cleanup"); } } elseif (is_file($target)) { unlink($target); } else { $this->logger->error("Could not delete the folder or file: $target"); } }
关键修改点
- 标准化路径:用
rtrim和DIRECTORY_SEPARATOR确保路径末尾有分隔符,避免$target . '*'变成/path/to/dir*(可能误匹配到其他同名前缀的目录)。 - 匹配隐藏文件:
{,.}*搭配GLOB_BRACE,同时覆盖普通文件(*)和隐藏文件(.*)的匹配。 - 过滤特殊目录:跳过
.和..,防止递归处理上级目录或者陷入无限循环。 - 额外校验:删除前再检查目录状态,避免因意外残留文件导致的报错,也方便排查问题。
这样修改后,不管目录里有没有隐藏文件,都能被彻底清理,空目录也能正常删除啦!
内容的提问来源于stack exchange,提问作者Tuz
相关产品推荐
相关产品推荐

