c++递归复制目录需手动遍历而非直接调用std::filesystem::copy,因后者不自动创建父目录、不强制覆盖只读文件、不处理符号链接且不保留属性;应使用recursive_directory_iterator逐项创建路径、区分目录/文件、显式设置权限与时间戳。

如何用 C++ 递归复制整个目录(含子目录和文件)
标准 C++ 库(C++17 起)提供了 std::filesystem,但它的 copy 函数默认不支持“强制覆盖 + 递归创建目标路径”的组合行为——直接调用 std::filesystem::copy(src, dst, std::filesystem::copy_options::recursive) 在目标目录已存在且只读时会失败,且不会自动创建缺失的父目录(如果 dst 路径中间某层不存在)。
为什么 std::filesystem::copy 直接用容易出错
常见报错包括:filesystem error: cannot copy: No such file or directory(目标父目录不存在)、Permission denied(目标文件只读)、File exists(默认不覆盖)。它也不处理符号链接的复制策略(是否解引用),更不提供进度反馈或细粒度错误恢复能力。
-
std::filesystem::copy_options::create_symlinks和skip_symlinks必须显式指定,否则遇到符号链接会抛异常 - 若目标路径中某级目录不存在,
copy不会尝试创建——得先手动调用std::filesystem::create_directories(dst.parent_path()) - 对已存在的同名文件,默认拒绝覆盖;需叠加
overwrite_existing才生效
一个可靠、可移植的递归复制实现要点
核心逻辑是手动遍历源目录树,逐项创建目标路径并复制内容。关键不是“一行调用”,而是控制三件事:路径创建、文件/目录区分、内容写入方式。
- 用
std::filesystem::recursive_directory_iterator遍历源目录,比copy更可控 - 对每个
entry,计算其相对于源根的相对路径,再拼接到目标根上,得到目标路径dst_path - 若
entry是目录,调用std::filesystem::create_directory(dst_path)(注意:不是create_directories,因为路径已按层级顺序遍历) - 若
entry是普通文件,先确保dst_path.parent_path()存在(create_directories),再用std::filesystem::copy_file(src_path, dst_path, std::filesystem::copy_options::overwrite_existing) - 对符号链接,根据需求选择
std::filesystem::read_symlink(entry.path())后重建,或跳过
Windows 下要注意的权限与属性细节
Windows 的 std::filesystem::copy_file 默认不保留文件属性(如只读、隐藏)和时间戳,而 cp -r 会保留。若需等效行为,必须额外调用 std::filesystem::permissions 和 std::filesystem::last_write_time。
- 复制后立即设置权限:
std::filesystem::permissions(dst_path, std::filesystem::status(src_path).permissions()) - 同步修改时间:
std::filesystem::last_write_time(dst_path, std::filesystem::last_write_time(src_path)) - Windows 上若源文件为只读,
copy_file可能失败,需先清除目标路径的只读属性(permissions(dst_path, perms::owner_write, perm_options::add))再覆盖
跨平台时,这些属性操作在 Linux/macOS 上基本无副作用,但 Windows 上缺了就会导致结果与 cp -r 行为明显不同。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











