默认不会递归复制子目录;需显式指定fs::copy_options::recursive才进入子目录,配合overwrite_existing可覆盖同名文件,但权限、时间戳等元数据需手动同步,windows长路径需系统级配置支持。

filesystem::copy 会递归复制子目录吗?
默认不会。直接调用 filesystem::copy(src, dst) 对目录只做“浅拷贝”——即创建同名空目录,不复制任何内容,还可能抛出 filesystem::filesystem_error(错误码为 not_supported 或 is_a_directory)。这是新手最常卡住的第一步。
必须显式传入 copy_options::recursive 才触发递归行为:
fs::copy(src_dir, dst_dir, fs::copy_options::recursive);
但注意:这仍不是“克隆”,它默认会跳过已存在的同名文件(不覆盖),也不处理符号链接、权限、最后访问时间等元数据。
如何让 copy 真正“克隆”而非“同步”?
克隆要求目标完全一致:覆盖已有文件、保留权限、不忽略隐藏项、不因路径存在而中断。关键靠组合 copy_options 标志位:
-
fs::copy_options::recursive—— 进入子目录 -
fs::copy_options::overwrite_existing—— 覆盖目标中同名文件/目录 -
fs::copy_options::skip_symlinks(可选)—— 避免把符号链接本身当普通文件复制(否则会复制目标文件内容) -
fs::copy_options::copy_symlinks(可选)—— 若需原样保留符号链接结构
典型克隆调用:
fs::copy(src, dst, fs::copy_options::recursive | fs::copy_options::overwrite_existing);
⚠️ 注意:overwrite_existing 对目录无效(目录无法“覆盖”,只能先删后建),所以若 dst 已存在且是目录,copy 会尝试向其中合并内容;如需严格“清空再写”,得手动 fs::remove_all(dst) 再 copy。
权限、时间戳、符号链接这些元数据能一并复制吗?
不能。C++17 的 filesystem::copy 只复制文件内容和基础权限(由 OS 默认 umask 或目标父目录决定),不复制 last_write_time、last_access_time、所有权(owner/group)、ACL 或扩展属性。
如果你需要完整克隆(比如备份或部署场景),得自己补全:
- 用
fs::last_write_time(src_entry, fs::last_write_time(dst_entry))同步修改时间 - 用
fs::permissions(dst_path, fs::status(src_path).permissions())恢复权限位 - 对符号链接,先判断
fs::is_symlink(src_entry),再用fs::read_symlink()+fs::create_symlink()
这些操作必须在 copy 完成后遍历目标树执行,且要注意顺序:先改权限,再改时间,否则某些系统会重置时间戳。
Windows 下路径长度超 260 字符怎么办?
默认情况下,Windows API 会拒绝长路径,导致 filesystem::copy 抛出异常,错误信息类似 The system cannot find the path specified(即使路径真实存在)。
解决方案只有两个:
- 在程序启动时调用
SetCurrentDirectory(L"\\?\C:\full\path")切换到长路径根目录下(需 Unicode 版本) - 更可靠的是:编译前定义
_HAS_AUTO_PTR_ETC 1并确保使用 VS2019+,同时在项目属性中启用“启用 Windows Long Path Support”(即清单中添加longPathAware=true)
纯 C++ 标准库无绕过方案,filesystem 底层仍走 Win32 API。Linux/macOS 无此限制。
实际克隆逻辑里,长路径问题往往在递归深处才暴露,建议在 copy 前先用 fs::exists() 和 fs::status() 预检关键路径,比等崩溃再查更省事。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











