Directory.GetFiles 获取文件后用 File.Move 批量重命名最可靠:需清除只读属性、校验目标路径、手动解析多点扩展名、逐文件异常捕获并记录。

用 Directory.GetFiles 获取所有文件再批量重命名
直接遍历目标文件夹下的文件是第一步,Directory.GetFiles 比 Directory.EnumerateFiles 更适合批量操作,因为返回的是完整路径数组,便于后续统一处理。注意要指定搜索选项(如 SearchOption.AllDirectories)来控制是否递归子目录。
常见错误是忽略文件只读属性或权限问题,导致 File.Move 抛出 UnauthorizedAccessException 或 IOException。建议先用 FileAttributes.ReadOnly 检查并清除只读位:
var files = Directory.GetFiles(@"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
var attr = File.GetAttributes(file);
if ((attr & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
File.SetAttributes(file, attr & ~FileAttributes.ReadOnly);
var dir = Path.GetDirectoryName(file);
var ext = Path.GetExtension(file);
var newName = Path.Combine(dir, "prefix_" + Path.GetFileNameWithoutExtension(file) + ext);
File.Move(file, newName);
}
File.Move 是重命名的唯一可靠方式
C# 中没有独立的“重命名”函数,File.Move 是实际且唯一推荐的方式——它在同卷(同一磁盘分区)下是原子重命名操作,不涉及内容复制,速度快、安全。跨卷调用 File.Move 会自动转为复制+删除,此时若中途失败可能留下残留文件。
关键注意事项:
-
File.Move的第二个参数(新路径)必须包含完整文件名和扩展名,不能只传新文件名 - 目标路径不能已存在,否则抛出
IOException;需提前用File.Exists判断并处理冲突(如跳过、覆盖或加序号) - 不要用
File.Copy+File.Delete替代,容易出竞态或残留
按规则生成新文件名时慎用 Path.GetFileNameWithoutExtension
这个方法看似方便,但对含多个点的文件名(如 archive.tar.gz)会截掉第一个点之后全部内容,变成 archive,丢失真实扩展名。如果想保留完整扩展链,应手动解析或改用正则匹配最后的点位置。
更稳妥的做法:
string fileName = Path.GetFileName(file);
int lastDot = fileName.LastIndexOf('.');
string namePart = lastDot > 0 ? fileName.Substring(0, lastDot) : fileName;
string extPart = lastDot > 0 ? fileName.Substring(lastDot) : "";
string newName = Path.Combine(dir, $"v2_{namePart}{extPart}");另外,Windows 文件系统对大小写不敏感,但 File.Move 传入大小写不同的名字(如 FILE.TXT → file.txt)仍会成功,这在某些场景下可能造成混淆,需明确业务是否需要保持大小写一致性。
批量操作前务必加异常捕获和日志输出
文件系统操作不可逆,尤其批量重命名一旦出错(比如路径拼错、编码异常、中文乱码),可能让整个文件夹陷入混乱。不要依赖 try-catch 包裹整个循环——那样会掩盖具体哪一步失败。
推荐逐文件 try-catch,并记录失败项:
foreach (var file in files)
{
try
{
// ... 构造 newName
File.Move(file, newName);
Console.WriteLine($"OK: {Path.GetFileName(file)} → {Path.GetFileName(newName)}");
}
catch (Exception ex)
{
Console.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.Message}");
// 可选:写入日志文件或收集 failedList
}
}特别注意:如果文件名含 Unicode 字符(如中文、emoji),确保控制台或日志编码支持 UTF-8,否则 Console.WriteLine 可能显示乱码,但不影响实际重命名结果。
真正麻烦的不是语法,而是路径拼接时的斜杠方向、相对/绝对路径混用、以及没检查目标文件是否存在就强行覆盖——这些细节一错,整批文件就可能被误删或覆盖。










