Directory.GetFiles最稳妥,因其明确控制范围、避免路径拼接错误;需注意绝对路径、SearchOption、File.Exists校验、预生成新名、UTF-8编码、异常隔离及长路径处理。

用 Directory.GetFiles 获取文件列表再逐个重命名最稳妥
直接遍历目录时容易漏掉子目录或误操作隐藏文件,Directory.GetFiles 能明确控制范围和过滤条件。它返回的是完整路径字符串数组,避免手动拼接路径出错。
常见错误是传入相对路径但当前工作目录不一致,导致找不到文件;或者没加 SearchOption.AllDirectories 却想处理子文件夹——这时根本不会进入下层。
- 要处理当前目录所有
.txt文件:Directory.GetFiles(@"C:MyFolder", "*.txt") - 要包含子目录:
Directory.GetFiles(@"C:MyFolder", "*.*", SearchOption.AllDirectories) - 重命名前务必检查目标路径是否已存在,否则
File.Move会抛IOException - 建议先用
Path.GetFileNameWithoutExtension和Path.GetExtension拆分原名,避免字符串截取越界
File.Move 是唯一安全的重命名方式,别用 File.Copy + File.Delete
File.Move 在同一卷内是原子操作,不会出现“复制成功但删除失败”导致文件残留的问题。跨卷时它内部自动降级为复制+删除,但你不用管——而自己手写两步,出错概率高得多。
典型翻车场景:循环中用 File.Copy 写到同名文件,结果覆盖原文件后 File.Delete 又失败,原始数据就没了。
- 源路径和目标路径必须都是绝对路径,相对路径在循环中极易错乱
- 目标文件已存在时
File.Move直接抛异常,需提前用File.Exists判断并处理(跳过/覆盖/改名) - 不要在遍历
Directory.GetFiles返回的数组时直接对数组元素调File.Move并更新数组——数组内容不会变,后续索引会错位
批量重命名时序问题:先生成新名,再统一执行移动
如果边读边改名,比如把 “1.jpg” → “2.jpg”、“2.jpg” → “3.jpg”,第二次就会因原文件已被改走而失败。真实场景里,文件名常含序号、日期等动态部分,必须预计算全部新路径,再顺序执行。
另一个坑是中文或特殊字符路径——.NET 默认用系统编码,但某些旧项目设置了 Encoding.Default,导致 File.Move 报 ArgumentException。.NET Core / .NET 5+ 已默认 UTF-8,老框架建议显式指定 Encoding.UTF8 处理文件名字符串。
- 用
List<(string oldPath, string newPath)>存储映射关系,避免嵌套循环 - 新文件名建议用
Path.Combine拼接,别用+或string.Format拼路径分隔符 - 对含时间戳的重命名,注意
DateTime.Now在循环中可能重复,改用DateTime.UtcNow.ToString("yyyyMMddHHmmssfff")
带进度和错误隔离的实用封装思路
真实批量任务常有几百上千文件,卡住或报错时不能全盘失败。需要单文件级 try/catch,记录失败项,同时反馈进度。
别用 BackgroundWorker(WinForms 旧货),现代写法直接上 async Task + IProgress<int>,UI 线程安全又轻量。控制台程序则用简单计数即可。
- 每个
File.Move包一层try/catch (IOException ex),记录ex.Message和原路径 - 进度值建议按完成数 / 总数计算,而非字节数——重命名不涉及大小,算它没意义
- 若需撤销,提前把原路径→新路径映射存到临时 JSON 文件,失败时可反向扫一遍还原
- 特别注意长路径:Windows 默认限制 260 字符,启用
longPathAware=true并用\?前缀才能突破










