std::filesystem::copy 默认不递归,需显式传入 recursive 选项;目标目录必须不存在或为空;跨平台需注意路径语义、权限、符号链接处理及 win32 的手动遍历限制。

std::filesystem::copy 无法递归复制整个文件夹
标准 C++17 的 std::filesystem::copy 默认行为是「不递归」——它遇到子目录会直接抛出 std::filesystem::filesystem_error,错误信息类似 Operation not permitted 或 Is a directory。这不是权限问题,而是函数签名明确要求你主动指定递归策略。
正确做法是传入 std::filesystem::copy_options::recursive:
std::filesystem::copy("src_dir", "dst_dir", std::filesystem::copy_options::recursive);
- 目标路径
"dst_dir"必须不存在,或必须是空目录;否则会报File exists - 若目标已存在且非空,需先手动清空或删除(
std::filesystem::remove_all) - 该调用会自动创建中间缺失的父目录(如
dst_dir/sub/a.txt的sub目录)
Windows 下用 CopyFileEx 需要自己遍历目录树
Win32 API 的 CopyFileEx 只处理单个文件,没有内置文件夹拷贝能力。想用它实现目录复制,必须手动递归遍历源目录,对每个文件调用 CopyFileEx,对每个子目录调用 CreateDirectory。
关键点:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
FindFirstFile/FindNextFile遍历时,注意跳过"."和".."目录项 - 判断是否为目录:检查
WIN32_FIND_DATA.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY -
CopyFileEx支持进度回调和取消,但目录层级深时容易栈溢出——建议用显式栈(std::stack)替代递归函数
跨平台可移植方案:组合 std::filesystem + 手动控制
纯 C++17 方案最稳妥,但要注意几个边界:
- 源路径末尾带不带
/影响语义:copy("a/", "b")表示把a下所有内容复制到b;而copy("a", "b")表示把整个a目录(含名字)复制成b/a - 若只想复制内容(不建外层目录),推荐先创建目标根目录,再遍历源目录逐项复制:
std::filesystem::create_directories("dst_dir");
for (const auto& entry : std::filesystem::recursive_directory_iterator("src_dir")) {
auto rel = std::filesystem::relative(entry.path(), "src_dir");
auto dst = "dst_dir" / rel;
if (entry.is_regular_file()) {
std::filesystem::copy_file(entry.path(), dst, std::filesystem::copy_options::overwrite_existing);
} else if (entry.is_directory()) {
std::filesystem::create_directories(dst);
}
}
- 上面代码能精确控制覆盖行为、跳过符号链接(默认不跟随)、避免
copy的“目标必须为空”限制 - 性能上比单次
copy(..., recursive)略低,但更可控,尤其适合需要过滤文件类型或加日志的场景
权限与符号链接:Linux/macOS 上的隐性陷阱
在类 Unix 系统中,std::filesystem::copy 默认不复制文件权限(mode),也不解析符号链接——它会把链接本身当普通文件复制过去(即复制 symlink 文件,而非其指向目标)。
如果需要保留权限或解引用链接:
- 加
std::filesystem::copy_options::copy_symlinks→ 复制链接文件本身(默认行为) - 加
std::filesystem::copy_options::skip_symlinks→ 跳过链接 - 加
std::filesystem::copy_options::recursive | std::filesystem::copy_options::copy_symlinks→ 仍只复制链接,不解引用 - 真正解引用并复制目标内容?必须手动
std::filesystem::is_symlink判断后调用read_symlink,再走文件复制逻辑 - 权限需额外调用
std::filesystem::permissions设置,不能靠copy自动继承
这些细节在开发跨平台工具时特别容易被忽略,一跑 Linux 就发现权限不对或链接失效。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










