rmdir() 只能删除空目录,非空时返回 false 并触发 e_warning;删除非空目录需手动递归清空再调用 rmdir(),注意隐藏文件、权限及 windows 文件锁定问题。

rmdir() 只能删空目录,直接调用非空目录会失败并触发 E_WARNING,返回 false。别指望它自动清空再删——它连警告都不告诉你目录为啥不空。
为什么 rmdir() 总是返回 false
常见错误现象:明明路径对、权限也够,rmdir($path) 还是返回 false,控制台还冒出一行警告:Warning: rmdir(...): Directory not empty。
根本原因就两个:
- 目录里有文件(包括隐藏文件如
.gitignore或.DS_Store) - 目录里有子目录(哪怕只有一层,
rmdir()也不认) - PHP 进程对目录或其父级没有
write和execute权限(Linux/macOS 下缺x权限会导致 opendir 失败,间接让递归清理也卡住)
注意:scandir() 会列出 . 和 ..,但真实文件/子目录得靠 array_diff(scandir($dir), ['.', '..']) 才能干净提取——漏掉这个,递归函数可能跳过隐藏文件。
删除非空目录必须自己写递归逻辑
PHP 没有内置的 rmtree(),你得组合 scandir()、is_dir()、unlink() 和 rmdir()。
推荐写法(简洁可靠,兼容 PHP 5.6+):
function deldir(string $dir): bool
{
if (!is_dir($dir)) {
return true; // 目录不存在,算删除成功
}
$items = array_diff(scandir($dir), ['.', '..']);
foreach ($items as $item) {
$path = $dir . '/' . $item;
is_dir($path) ? deldir($path) : unlink($path);
}
return rmdir($dir);
}
// 用法
deldir('/tmp/myproject');
关键点:
- 不用
@opendir()抑制警告——掩盖问题不如早点暴露权限或路径错误 - 先清内容再删目录,顺序不能反
- 函数返回
bool,方便外层判断成败,比如配合if (!deldir($dir)) { throw new RuntimeException("Cleanup failed"); }
ftp_rmdir 和 streamWrapper::rmdir 不是 rmdir() 的替代品
看到名字带 rmdir 就以为能通用?错。
-
ftp_rmdir()只作用于 FTP 连接上的远程路径,且同样要求目录为空;它和本地rmdir()完全无关,参数类型、错误机制、上下文都不同 -
streamWrapper::rmdir()是自定义流包装器里的方法,只有你实现了自己的StreamWrapper类,并在其中定义了该方法,rmdir()调用才会走到这儿;普通文件系统下它压根不生效 - 三者签名相似,但行为隔离——混用会导致静默失败或不可预期的 warning
如果你正在封装一个“通用删除”工具类,务必按协议分发:本地路径走递归 + rmdir(),FTP 路径走 ftp_rmdir(),自定义协议走对应 wrapper 方法。
最易被忽略的细节:Windows 下目录权限继承机制和 Linux 不同,有时 rmdir() 报错不是因为没权限,而是某个子文件被其他进程(如 IDE、杀毒软件)锁住了——这种情况下,递归函数里 unlink() 会先失败,导致后续 rmdir() 永远收不到空目录。加个 clearstatcache() 和重试逻辑,比硬扛更实际。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











