directory.createdirectory仅创建空目录,不能复制内容;需手动递归遍历文件和子目录,用file.copy配合path.combine实现拷贝,并处理路径存在性、文件占用、性能优化等问题。

Directory.CreateDirectory 不能替代拷贝
新建空文件夹不等于复制目录——Directory.CreateDirectory 只创建路径,不会读取源内容。很多人调用它后发现目标文件夹“空空如也”,就是误以为它有拷贝能力。
- 真正要拷贝,必须遍历源目录的
Directory.GetFiles和Directory.GetDirectories - 递归时注意:目标子目录得提前建好,否则
File.Copy会因路径不存在而抛DirectoryNotFoundException - 别直接用
File.Copy(src, dst)而不检查dst所在目录是否存在,这是最常触发异常的地方
用 File.Copy + 递归处理子目录最可控
标准库没提供一键拷贝整个目录的函数(FileSystem.CopyDirectory 是 .NET Core 5+ 新增,旧项目不可用),所以手动递归仍是主流做法,尤其要兼容 .NET Framework 4.7.2 或更早版本。
- 先调用
Directory.CreateDirectory确保目标根目录存在 - 对每个
File:拼出目标完整路径,再调用File.Copy(srcPath, dstPath, true)(第三个参数true表示覆盖) - 对每个
Directory:递归调用自身,传入源子路径和对应的目标子路径 - 注意路径拼接用
Path.Combine,别用字符串拼"\"或"/",Windows/Linux 兼容性就靠它
遇到“文件正被另一个进程使用”怎么办
IOException: The process cannot access the file 'xxx' because it is being used by another process. 这类错误不是代码写错了,而是运行时环境问题,硬重试或忽略都可能丢数据。
- 先确认是否自己代码里打开了该文件但没
.Dispose()或using——比如用FileStream读完没关 - 检查杀毒软件、OneDrive、Windows Search 是否正在索引该目录(临时暂停可验证)
- 不要加
Thread.Sleep(100)盲目重试;真需要重试,建议最多 3 次,每次间隔递增,并记录日志 - 若只是想跳过锁定文件,捕获
IOException后继续循环,但务必记日志,否则后期排查无从下手
大文件或深层嵌套时性能明显变慢
纯递归 + File.Copy 在拷贝几十 GB 或上万级小文件时,I/O 等待会拖慢整体速度,且内存占用未必高,瓶颈其实在系统调用频次和路径解析开销。
- 避免在循环里反复调用
Path.Combine多次拼同一路径——提前算好源/目标基路径,用相对子路径推导 - 小文件多时,考虑用
Parallel.ForEach并行拷贝,但注意磁盘是共享资源,并行数设为Environment.ProcessorCount / 2更稳妥 - 别用
Directory.EnumerateFiles(..., SearchOption.AllDirectories)一次性加载全部路径到内存——深层嵌套下容易OutOfMemoryException,改用递归 +Enumerate分批
File.Copy 就直接炸,而且错误信息里根本看不出缺的是哪一级。










