c++17 可递归复制目录,但需显式指定 recursive 与 overwrite_existing 等选项,提前创建目标目录,捕获权限异常,谨慎处理符号链接及 windows 长/unicode 路径。

标准 C++17 的 <filesystem></filesystem> 库可以直接递归复制整个文件夹,无需第三方依赖,但必须注意路径存在性、权限和符号链接的默认行为。
用 std::filesystem::copy 递归复制目录
这是最直接的方式,但容易忽略参数标志组合 —— 默认行为不递归、不创建缺失父目录、不覆盖已存在文件。
- 必须显式传入
std::filesystem::copy_options::recursive才会进入子目录 - 建议同时加上
std::filesystem::copy_options::skip_existing或std::filesystem::copy_options::overwrite_existing明确覆盖策略 - 目标父目录(即目标文件夹的所在路径)必须已存在;
copy不自动创建上级目录,需提前调用std::filesystem::create_directories - 示例:
namespace fs = std::filesystem; fs::create_directories("dst_folder"); // 先确保目标目录可写 fs::copy("src_folder", "dst_folder", fs::copy_options::recursive | fs::copy_options::overwrite_existing);
复制时遇到 “Permission denied” 或 “Operation not permitted” 怎么办
常见于 macOS/Linux 下复制带扩展属性(xattr)或不可执行位的文件,或 Windows 下只读文件;std::filesystem::copy 默认尝试保留所有属性,失败即抛异常。
- 捕获
std::filesystem::filesystem_error并检查.code().value():Linux/macOS 常见 1(EPERM)、13(EACCES),Windows 常见 5(ACCESS_DENIED) - 若只需内容复制,去掉
copy_options::copy_symlinks和copy_options::skip_symlinks,并避免对特殊文件(如设备节点)操作 - 更稳妥做法:手动遍历 +
fs::copy_file,跳过无法访问的条目(用fs::status检查fs::status_known和fs::perms::owner_read)
符号链接(symlink)默认不被解引用,要小心“空目录”假象
std::filesystem::copy 对符号链接的处理取决于选项:默认既不复制链接本身,也不复制它指向的内容,导致目标中该路径消失或报错。
立即学习“C++免费学习笔记(深入)”;
- 想原样复制符号链接(即在目标也建一个指向相同路径的 symlink),加
fs::copy_options::copy_symlinks - 想复制符号链接所指的真实内容(递归展开),加
fs::copy_options::dereference_symlinks - 两者互斥;若都未指定,遇到 symlink 时行为由实现定义,GCC libstdc++ 通常跳过,MSVC STL 可能抛异常
- 务必在调用前用
fs::is_symlink(p)检查,避免静默丢失
Windows 下长路径和 Unicode 路径必须用宽字符 API
即使你用了 std::filesystem::path,底层仍依赖 Windows API;若路径含中文、日文或超过 MAX_PATH(260 字符),窄字符串构造的 path 会失败或截断。
- 始终用
std::filesystem::path的宽字符串构造函数:fs::path(L"中文路径\folder"),而非"中文路径\folder" - 编译时启用
/utf-8(MSVC)或-finput-charset=utf-8(GCC/Clang),并确保源文件保存为 UTF-8 with BOM(MSVC)或无 BOM(GCC) - 不要用
fs::u8path处理含非 ASCII 的窄字符串 —— 它不进行编码转换,只是 reinterpret_cast,极易出错
真正麻烦的不是“怎么写一行 copy”,而是路径合法性校验、错误恢复策略、以及跨平台 symlink 和权限语义差异。这些细节不写进 try-catch 或预检查,上线后第一份用户反馈大概率就是“复制失败,但没报错”。











