在C#中批量重命名文件夹内的文件,核心思路是先获取文件列表,再根据自定义规则生成新名称,最后调用系统API移动或重命名。这种方式比手动改快几十倍,也方便在持续集成或日常运维中复用。

一、获取文件夹中的文件列表
最基础的方法是使用System.IO.Directory类的GetFiles方法。它可以返回指定目录下的所有文件路径,也支持搜索子目录。如果只处理当前目录,传SearchOption.TopDirectoryOnly即可;需要递归就换成AllDirectories。
下面示例演示如何拿到一个文件夹里所有的jpg文件,并打印原名称。注意路径要用绝对路径或相对于程序的相对路径,避免找不到目录而抛异常。
using System;
using System.IO;
class Program
{
static void Main()
{
string folderPath = @"D:test_images";
// 仅搜索当前目录下的jpg文件
string[] files = Directory.GetFiles(folderPath, "*.jpg", SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
Console.WriteLine("原文件:" + Path.GetFileName(file));
}
}
}
除了Directory.GetFiles,还可以用DirectoryInfo对象,它返回FileInfo集合,能同时拿到创建时间、扩展名等属性,在按时间规则重命名时更方便。两者的底层都调用操作系统文件枚举接口,性能差异不大,按编码习惯选择即可。
二、设计可配置的重命名规则
所谓按规则修改,通常指加前缀、加序号、替换关键字或基于时间重新构造。我们可以用一个简单的函数把旧路径和新名称生成逻辑解耦。例如给每个文件加proj_前缀并保留扩展名,只要拼接字符串就行。
如果规则复杂,比如把IMG2023.jpg变成2023_img_001.jpg,就需要解析原文件名。这时用正则表达式提取数字或日期段最稳妥。下面的代码展示一个带序号的重命名规则,序号从1开始补零到三位。
using System;
using System.IO;
using System.Text.RegularExpressions;
class Renamer
{
public static string BuildNewName(string oldPath, int index)
{
string dir = Path.GetDirectoryName(oldPath);
string ext = Path.GetExtension(oldPath);
// 去掉扩展名后的纯名
string baseName = Path.GetFileNameWithoutExtension(oldPath);
// 示例规则:前缀proj_ + 三位序号 + 原纯名 + 扩展名
string seq = index.ToString("D3");
string newName = $"proj_{seq}_{baseName}{ext}";
return Path.Combine(dir, newName);
}
}
规则函数写好之后,主流程只需遍历文件、计算新路径、调用File.Move。需要提醒的是,如果新路径已存在,File.Move在Windows上会抛IOException,因此批量前应先检查目标是否存在,或先把所有新名算好做冲突检测。
三、执行批量重命名与异常处理
真正执行阶段建议用try-catch包裹每一次移动,避免单个文件出错导致整个任务中断。同时可把成功和失败分别记录,方便后续补处理。以下示例演示了带异常捕获的循环重命名。
using System;
using System.IO;
class Program
{
static void Main()
{
string folder = @"D:test_images";
string[] files = Directory.GetFiles(folder, "*.*", SearchOption.TopDirectoryOnly);
int i = 1;
foreach (string f in files)
{
try
{
string newPath = Renamer.BuildNewName(f, i);
if (File.Exists(newPath))
{
Console.WriteLine("跳过,已存在:" + newPath);
}
else
{
File.Move(f, newPath);
Console.WriteLine($"重命名成功:{Path.GetFileName(f)} -> {Path.GetFileName(newPath)}");
}
}
catch (Exception ex)
{
Console.WriteLine("处理失败:" + f + " 原因:" + ex.Message);
}
i++;
}
}
}
上面的代码在控制台打印了每一步结果。若用于GUI或服务项目,可把控制台输出换成事件回调或日志组件。对于超大量文件,可考虑用Parallel.ForEach并行处理,但并行移动同一磁盘文件未必更快,还可能因竞态导致异常,一般顺序执行更可控。
四、递归处理子目录与扩展思路
当文件夹层级较深时,用SearchOption.AllDirectories能一次性拿到所有文件。但有时不同子目录要用不同规则,那就需要自己写递归,在每一层传入对应的前缀或格式化器。下面给出一个简单的递归示例。
using System;
using System.IO;
class Program
{
static void Walk(string dir)
{
foreach (string file in Directory.GetFiles(dir))
{
// 这里可调用前面的BuildNewName,也可按子目录定制
Console.WriteLine("待处理:" + file);
}
foreach (string sub in Directory.GetDirectories(dir))
{
Walk(sub);
}
}
static void Main()
{
Walk(@"D:test_root");
}
}
除了基础改名,还可以结合配置文件(如json)让规则外部化,程序启动时读取前缀、序号位数、是否递归等参数,这样同一个exe能适配多个项目。另外,若文件正在被占用,File.Move也会失败,可在异常里提示用户关闭相关程序后再跑脚本。
五、小结与注意事项
用C#写批量重命名工具并不复杂,关键是把获取文件、生成规则、执行移动三步拆清楚。实际项目中建议先在小样本目录试运行,确认新名符合预期再全量跑。对重要数据,重命名前最好先做备份或只输出新名映射表,人工核对后再执行真实移动。
此外,跨磁盘移动不能用File.Move直接完成,它仅支持同卷重命名;若涉及不同驱动器,要用File.Copy加File.Delete组合。理清这些边界情况,才能让批量改名程序稳定可靠地融入你的工作流。
C#文件批量重命名FileSystemInfo修改时间:2026-08-02 21:09:31