directory.getfiles 默认不递归子目录,需显式传 searchoption.alldirectories;大目录应改用 directory.enumeratefiles 避免内存溢出,且须手动捕获 unauthorizedaccessexception 等异常并限制递归深度防循环。

Directory.GetFiles 默认不进子目录,深层遍历必须显式传 SearchOption.AllDirectories;但真要处理大目录、权限异常或符号链接,它很快就不够用——得换 Directory.EnumerateFiles 加手动控制。
为什么 Directory.GetFiles("path") 总是漏文件?
它只查当前层,连一级子目录都不进。你看到的“漏”,八成是忘了第三个参数。
- 错误写法:
Directory.GetFiles("C:\Projects")→ 只返回 Projects 目录下的 .cs 文件,Models/Controllers 里的全没影 - 正确写法:
Directory.GetFiles("C:\Projects", "*.cs", SearchOption.AllDirectories) - 通配符必须带
*和点,"*.log"行,"log"或"log*"不匹配 - 路径含中文或空格没问题,但旧版 .NET Framework 在非 UTF-8 区域设置下可能乱码;.NET 5+ 默认安全
大目录卡死或内存爆掉?别用 GetFiles
它返回 string[],一次性把所有路径加载进内存。几万文件就吃掉几百 MB,UI 线程直接卡住。
- 换成
Directory.EnumerateFiles:返回IEnumerable<string></string>,边迭代边生成,内存占用基本恒定 - 不能对结果调
.ToArray()或.Count()—— 那就又退化成GetFiles行为 - 想统计数量又怕 OOM?边枚举边累加:
int count = 0; foreach (var f in EnumerateFiles(...)) count++; - 注意:
EnumerateFiles遇到被删文件可能抛IOException,外层建议包一层try/catch
访问被拒绝(UnauthorizedAccessException)就中断?得自己兜底
GetFiles 遇到 C:WindowsSystem32 或加密卷,直接崩;EnumerateFiles 虽然默认跳过无权限目录,但不报错也不通知——你根本不知道漏了哪块。
- 必须在
foreach每次迭代里捕获异常:try { Console.WriteLine(file); } catch (UnauthorizedAccessException) { continue; } - 别对整个
EnumerateFiles(...)调用包try——那只能捕第一次,后续照样崩 -
DirectoryNotFoundException也常见(比如挂载点断开),一并 catch 掉更稳妥 - 想感知失败位置?记下出错目录名,而不是静默跳过
跨平台符号链接和循环引用怎么防?
SearchOption.AllDirectories 在 Windows 上可能钻进 junction,在 Linux/macOS 上默认不跟 symlink——同一段代码,行为不一致。
- .NET 6+ 没有统一开关控制是否跟随链接,得按需处理
- Linux 下若需跟随,得用
FileSystemEnumerable或第三方库(如K4os.FileSystem) - NTFS 或 ext4 上都可能出现硬链接/软链接构成的循环路径,
EnumerateFiles会无限递归直到栈溢出或磁盘耗尽 - 生产环境务必加最大深度限制:自己维护递归层级计数,超深就
break或yield break
真正难的不是写出来,而是让代码在用户随便扔进来的路径上不崩、不卡、不漏、不循环——这些边界情况,往往只在上线后第一个凌晨三点的告警里才暴露出来。











