directory.delete("path")要求目录为空,否则抛出ioexception;正确做法是directory.delete(path, true)递归删除,或用enumeratefiles/enumeratedirectories分步清空内容但保留目录。

Directory.Delete 会报错:目录不为空
直接调用 Directory.Delete("path") 要求目标目录必须为空,否则抛出 DirectoryNotFoundException 或更常见的 IOException:“目录不是空的”。这不是权限问题,是设计使然——它只删空目录。
正确做法是先清空再删,或一步到位用带递归参数的重载:
-
Directory.Delete(path, true):第二个参数true表示递归删除所有子目录和文件,等效于“强制清空并删掉该目录本身” - 如果只想清空内容但保留空目录,不能靠
Delete,得手动遍历删
清空目录但保留文件夹本身(推荐用 Directory.GetFiles + Directory.GetDirectories)
常见需求是“把 D:\Temp 里的东西全干掉,但 D:\Temp 这个文件夹还得在”,这时 Delete(path, true) 不适用,因为它会连文件夹一起删掉。
安全高效的做法是分别获取文件和子目录列表,再批量删除:
var dir = @"D:\Temp"; foreach (var file in Directory.GetFiles(dir)) File.Delete(file); foreach (var subDir in Directory.GetDirectories(dir)) Directory.Delete(subDir, true);
注意点:
- 顺序很重要:先删文件,再删子目录;反过来可能因子目录非空导致
Delete(subDir, true)失败(实际不会,但逻辑更清晰) - 没有原子性保障,中途出错会导致目录处于半清理状态;如需强一致性,应加 try/catch + 回滚逻辑(比如记录已删项)
- 大量小文件时,
GetFiles可能分配大数组,内存压力明显;可改用Directory.EnumerateFiles流式处理
用 Directory.EnumerateFiles 避免内存暴涨
当目标目录有数万文件时,Directory.GetFiles 返回 string[] 会一次性加载全部路径到内存,可能触发 GC 或 OOM。而 EnumerateFiles 返回 IEnumerable<string></string>,按需迭代,开销低得多。
清空操作可这样写:
var dir = @"D:\Temp"; foreach (var file in Directory.EnumerateFiles(dir)) File.Delete(file); foreach (var subDir in Directory.EnumerateDirectories(dir)) Directory.Delete(subDir, true);
关键差异:
-
EnumerateFiles不保证顺序,也不捕获初始快照——如果遍历时有新文件写入,它可能被删也可能被跳过(取决于枚举器实现和文件系统行为) - 它不支持搜索模式(如
"*.log"),如需过滤,得配合Where或手动判断扩展名 - 在 NTFS 上性能接近,但在网络驱动器或 OneDrive 同步目录中,延迟更敏感,
Enumerate*更稳
权限不足、只读文件、正在使用的文件导致删除失败
即使代码逻辑正确,运行时仍常遇到 UnauthorizedAccessException、IOException(“进程无法访问文件,因为正由另一进程使用”)或“拒绝访问”提示。这不是 bug,是 Windows 文件系统约束。
应对策略要分情况:
- 只读文件:删前设为普通属性 ——
File.SetAttributes(path, FileAttributes.Normal) - 被占用文件:无法强制结束句柄,只能跳过或提示用户关闭相关程序(如日志文件被记事本打开)
- 权限问题:以管理员身份运行程序,或提前检查
Directory.GetAccessControl(代价高,一般不建议) - 符号链接/挂载点:
Directory.Delete(subDir, true)默认不跟进,需额外判断File.GetAttributes是否含ReparsePoint
真正难处理的是“删到一半失败后怎么恢复”——多数业务场景其实接受“尽力而为”,但关键路径必须记录失败项并提供重试入口。










