directory.delete(path) 默认只删空目录,删非空目录需加 true 参数;遇只读或权限问题会报错,需手动处理属性或捕获异常;命令行删除不安全,跨平台需注意挂载点和符号链接限制。

Directory.Delete() 会报错“目录不为空”?
直接调用 Directory.Delete(path) 只能删除空文件夹,一旦里面有任何文件或子目录,就会抛出 DirectoryNotFoundException 或更常见的 IOException:“目录不是空的”。这不是 bug,是设计使然——.NET 默认拒绝递归删除,防止误操作。
真正要删非空文件夹,必须显式传入第二个参数:true:
Directory.Delete(path, true); // true 表示递归删除所有子项
- 如果
path不存在,会直接抛DirectoryNotFoundException,建议先用Directory.Exists(path)判断 - 权限不足(如只读文件、系统文件、被其他进程占用)会导致删除失败,
true不会跳过这些错误,而是中断并抛异常 - 该方法是同步阻塞的,大文件夹可能卡住 UI 线程,WinForms/WPF 中应考虑用
Task.Run包裹
如何安全删除:跳过只读文件、忽略权限错误?
.NET 原生 Directory.Delete() 不提供“尽力而为”模式。遇到只读文件时,它不会自动清除只读属性;遇到访问被拒,也不会继续删剩下的内容。必须手动干预:
典型做法是先遍历所有文件,逐个取消只读属性,再执行删除:
foreach (var file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
{
var attr = File.GetAttributes(file);
if ((attr & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
File.SetAttributes(file, attr & ~FileAttributes.ReadOnly);
}
Directory.Delete(path, true);
-
SearchOption.AllDirectories是关键,漏掉这个就只处理根目录下的文件 - 不要用
File.SetAttributes(file, FileAttributes.Normal)—— 这会清掉隐藏、系统等其他属性,可能破坏应用行为 - 若需容忍部分文件删不掉(比如被记事本打开着),得自己写递归删除逻辑,捕获
UnauthorizedAccessException和IOException后 continue
用 PowerShell 或 cmd 替代?不推荐
有人倾向用 Process.Start("cmd", $"/c rmdir /s /q {path}") 调用命令行删除,理由是“更彻底”。实际问题很多:
- 路径含空格或特殊字符(如
&、()极易导致命令解析失败或执行意外命令 - 不同 Windows 版本中
rmdir对 Unicode 路径支持不一致,中文路径可能乱码或跳过 - 无法精确控制异常粒度——cmd 返回码只有 0/1,你不知道是“全删完了”还是“删了一半就崩了”
- 杀毒软件常拦截此类进程创建行为,尤其在企业环境中容易被策略阻止
除非明确需要兼容极老的 .NET Framework 1.x(早已淘汰),否则纯 C# 方案更可控、更可测。
跨平台注意:.NET Core/.NET 5+ 的行为差异
在 Linux/macOS 上用 Directory.Delete(path, true),行为基本一致,但有两个硬性限制:
- Linux 下无法删除挂载点(mount point)目录,即使为空也会报
IOException,且错误信息不提示原因 - 符号链接(symlink)本身会被删除,但默认不递归进入其指向的目标目录——这点和 Windows 一致,无需额外处理
- 文件系统权限模型不同:Windows 看 ACL,Linux/macOS 看 owner/group/mode,
UnauthorizedAccessException触发条件更严格,建议提前用File.GetAccessControl()(Windows)或stat命令(Unix)探查
真正容易被忽略的是:某些云存储模拟的本地路径(如 OneDrive、Google Drive 同步文件夹),即使显示为本地路径,Delete 可能触发后台同步冲突,返回看似随机的 IOException。这种场景必须加重试 + 指数退避,不能只靠 try/catch。










