Directory.GetFiles 默认不递归,需显式传 SearchOption.AllDirectories;遇权限错误会中断,应改用 Directory.EnumerateFiles 配合 try/catch;内存敏感场景优先选 EnumerateFiles;注意符号链接、循环引用及编码问题。

Directory.GetFiles 递归遍历会漏掉深层嵌套文件?
默认 Directory.GetFiles 不递归,只查当前目录。想扫完整树形结构,必须显式传入 SearchOption.AllDirectories 参数,否则子文件夹里的文件完全不会出现。
常见错误是直接调用 Directory.GetFiles("path") 后发现结果比资源管理器里看到的少很多——八成是忘了加第二个参数。
- 正确写法:
Directory.GetFiles("C:\MyFolder", "*.*", SearchOption.AllDirectories) - 若只要特定类型,把
"*.*"换成"*.log"或"config.json"即可 - 注意:如果目标路径含中文或特殊字符,确保编码无问题;.NET Core/.NET 5+ 默认 UTF-8,旧版 .NET Framework 在某些系统区域设置下可能读错文件名
访问被拒绝(UnauthorizedAccessException)怎么绕过?
遍历时遇到系统目录(如 C:WindowsSystem32)、回收站、加密卷或权限受限文件夹,Directory.GetFiles 会直接抛 UnauthorizedAccessException 并中断整个遍历——它不支持跳过错误继续执行。
必须改用 Directory.EnumerateFiles 配合手动异常捕获,才能实现“尽力而为”的扫描。
- 用
try/catch包裹每次MoveNext()或foreach迭代中的访问操作 - 不要对整个
EnumerateFiles调用加一层try——那只会捕获第一次失败,后续仍会崩 - 示例关键片段:
foreach (string file in Directory.EnumerateFiles(root, "*.*", SearchOption.AllDirectories)) { try { Console.WriteLine(file); } catch (UnauthorizedAccessException) { continue; } catch (DirectoryNotFoundException) { continue; } }
大目录下性能卡顿,内存爆满?
GetFiles 返回的是 string[],会一次性把所有路径加载进内存;几万个文件就可能吃掉上百 MB。而 EnumerateFiles 返回 IEnumerable<string></string>,按需生成,延迟执行,内存占用几乎恒定。
除非你明确需要数组长度、随机索引或反复遍历,否则一律优先选 EnumerateFiles。
- 注意:两者都可能因 NTFS 权限或符号链接陷入死循环,建议限制最大递归深度(自己计数),或用
FindFirstFileEx等 Win32 API 做更底层控制 - 若需过滤后再统计数量,别先
.ToArray().Length,改用Count()(但仍是全遍历)或边枚举边累加 - 避免在 UI 线程直接调用——哪怕用了
EnumerateFiles,大量磁盘 I/O 也会导致界面冻结,应丢进Task.Run
符号链接、硬链接、挂载点导致重复或死循环?
Windows 下的 Junction、SymbolicLink、Volume Mount Point 可能让同一物理文件被多个路径引用。EnumerateFiles 和 GetFiles 都不自动去重,也不检测循环引用,容易无限深入或返回重复项。
没有内置方案,只能自己处理:
- 用
File.GetAttributes(file)检查是否含FileAttributes.ReparsePoint,再结合FileSystemEnumerableOptions(仅 .NET 5+)跳过重解析点 - 维护一个已访问的
device ID + inode(通过GetFileInformationByHandle获取)哈希集合,判断是否重复 - 简单场景下,加个递归层级计数器(比如超过 32 层就 break),能拦住绝大多数意外循环
真实项目里,这类边界情况往往只在客户现场爆发——本地测试时用的都是干净路径,上线后一扫 NAS 或旧服务器立刻出问题。


















