批量重命名文件前须确保路径安全:仅对 filename() 部分正则替换,拼接 parent_path() 和新名;慎用 .*,优先锚定匹配;Unicode 场景用 wregex/wstring;遍历时显式 is_regular_file() 过滤并捕获异常;rename 前检查目标存在、跨分区(EXDEV)及文件占用;务必支持 --dry-run 预览。

用 std::regex_replace 批量改文件名前要先确保路径安全
直接对原始文件名调用 std::regex_replace 很容易出错——比如把 "log.txt.bak" 里的 ".txt" 替换掉,结果变成 "log.bak.bak"。关键不是正则写得有多酷,而是得在「完整路径」和「纯文件名」之间划清界限。
- 永远只对
std::filesystem::path::filename()部分做regex_replace,别碰parent_path() - 替换后要用
parent_path() / new_filename拼回完整目标路径,避免跨目录移动 - 正则模式里慎用
.*,优先用非贪婪或锚定(如^prefix_(.*)\.log$)防止误匹配 - 如果原名含 Unicode(Windows 上常见),
std::regex在 MSVC 中默认不支持 UTF-8 字符串,建议改用std::wregex+std::wstring路径
遍历目录时用 std::filesystem::recursive_directory_iterator 但得跳过子目录自身
很多人写 for (auto& p : std::filesystem::recursive_directory_iterator(dir)) 后,发现重命名把子目录也当文件处理了——其实 p 是个 directory_entry,它不自动区分类型。
- 必须显式调用
p.is_regular_file()过滤,否则可能尝试重命名一个目录,触发std::filesystem::rename报错Permission denied或Invalid argument - 遍历时加异常捕获:某些路径可能权限不足或被占用,用
std::error_code ec版本的is_regular_file(ec)避免程序中断 - 若需按深度控制(比如只处理当前层),改用
std::filesystem::directory_iterator,别硬套recursive_
std::filesystem::rename 失败的三个高频原因
正则替对了、路径拼对了,rename 还是失败?大概率卡在这三处。
- 目标路径已存在:C++ 标准规定
rename不覆盖,必须先exists(target)并手动remove(target)(注意权限) - 源和目标在不同磁盘分区(Windows 常见):此时
rename会失败并抛std::filesystem::filesystem_error,错误码为EXDEV,得退化为「复制 + 删除」 - 文件正被其他进程占用(如记事本打开着):Windows 上尤其敏感,
rename直接返回Access is denied,没太多办法,只能跳过或提示用户
实际跑起来前务必加预览模式和 dry-run 开关
批量重命名没有撤销键。哪怕正则测试通过,真实文件名里的空格、括号、特殊字符也可能让 regex_replace 行为偏移。
- 加一个
--dry-run参数,只打印「将从 A 改为 B」,不调用rename - 输出时用
std::quoted()包裹路径,一眼看出空格和引号问题:std::cout - 首次运行别全量处理,先用
std::views::take(5)(C++20)或简单计数限制前 3 个文件,确认逻辑无误再放开
最麻烦的从来不是正则怎么写,而是路径编码、跨分区、权限、并发占用这些边界情况——它们不会报编译错误,但会让脚本在客户机器上静默失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











