std::filesystem::copy_file复制失败却无报错,实为未捕获异常所致;必须用try/catch处理或显式指定copy_options策略,且该函数不支持进度反馈与符号链接原样复制。

std::filesystem::copy_file 为什么复制失败但没报错
默认情况下 std::filesystem::copy_file 遇到目标已存在会直接抛 std::filesystem::filesystem_error,但很多人没捕获异常,程序静默崩溃或跳过——这不是“没报错”,是异常没处理。C++17 标准里它不返回 bool,也不设 errno,全靠异常传递错误。
- 必须用
try/catch包裹,或传入std::filesystem::copy_options::skip_existing等显式策略 - 目标路径父目录不存在时,即使加了
copy_options::create_parents也无效——这个选项只对create_directories生效,copy_file不递归建目录 - 权限问题常被忽略:源文件不可读、目标目录不可写、Windows 下目标文件正被占用,都会触发同一种异常,需检查
.code().value()区分(如5是拒绝访问,17是路径不存在)
覆盖、跳过、合并:copy_options 的真实行为差异
std::filesystem::copy_options 不是开关组合,而是互斥策略枚举,传多个会编译失败。常见误用是以为 skip_existing | overwrite_existing 合法,实际只能选其一。
-
std::filesystem::copy_options::overwrite_existing:目标存在则覆盖,但不会校验内容是否相同,纯字节覆盖 -
std::filesystem::copy_options::skip_existing:目标存在则跳过,不报错,也不更新 mtime -
std::filesystem::copy_options::update_existing:仅当源比目标新(mtime 更大)时才覆盖,否则跳过——这是最接近“增量同步”的选项
示例:std::filesystem::copy_file("a.txt", "b.txt", std::filesystem::copy_options::update_existing);
Windows 下硬链接 / 符号链接复制的陷阱
默认 copy_file 复制的是链接指向的目标内容,不是链接本身。想复制符号链接文件(.lnk)或硬链接元数据,得手动处理。
立即学习“C++免费学习笔记(深入)”;
- 用
std::filesystem::is_symlink(src)先判断,再用std::filesystem::read_symlink(src)获取目标路径,最后调用std::filesystem::create_symlink() - Windows 上普通用户无法创建符号链接,需管理员权限或开启开发者模式;硬链接仅限同一卷且不能跨文件系统
-
copy_options::copy_symlinks这个选项并不存在——标准库至今没提供“原样复制链接”的内置支持
大文件复制卡顿?别用 copy_file 做进度反馈
std::filesystem::copy_file 是原子操作,内部调用 OS 底层接口(如 Windows 的 CopyFileEx 或 Linux 的 copy_file_range),没有回调机制,也无法中断或获取实时进度。
- 需要进度条或取消功能,必须自己实现流式复制:用
std::ifstream+std::ofstream分块读写,每次读4096或65536字节 - 注意二进制模式:两个流都得加
std::ios::binary,否则 Windows 下换行符会被悄悄转换 - 小文件(copy_file 更快;大文件(>100MB)自己控制缓冲区能避免内存峰值,也方便插入日志或 sleep 防止 UI 冻结
真正难的不是怎么写,是判断该不该用 copy_file——它适合“确定要全量覆盖且无需干预”的场景,一旦涉及交互、策略混合或细粒度控制,就得退回到手动 I/O。



















