std::filesystem::exists 可能因权限不足、悬空符号链接或跨挂载点返回 false 而非路径不存在;推荐用 status() + is_symlink() + symlink_status() 组合判断,并先调用 status_known() 确认状态已知。

std::filesystem::exists 检查路径前先确认权限和符号链接行为
它不报错,但可能返回 false 却不是因为路径不存在——比如没读权限、跨挂载点、或指向一个损坏的符号链接。C++17 的 std::filesystem 默认不自动解析符号链接,exists(path) 对悬空链接返回 false,而 exists(path, ec) 过载能避免异常但依然受 same-file-system 限制。
- 用
status(path)+is_symlink()+symlink_status()组合判断更稳妥 - 检查前建议先用
std::filesystem::status_known(status(path))确认状态是否已知,避免误判 - Linux 下若路径在 NFS 或 procfs 上,
exists可能返回false即使路径合法——这不是 bug,是底层stat()行为透出
std::filesystem::copy 复制文件时注意递归、覆盖和权限继承
默认不递归、不覆盖、不保留权限。直接调 copy(src, dst) 在目标存在时抛 std::filesystem::filesystem_error,错误信息类似 "File exists",而不是静默跳过。
- 要覆盖:加
std::filesystem::copy_options::overwrite_existing - 要递归复制目录:加
std::filesystem::copy_options::recursive - 想保留时间戳和权限?得手动调
last_write_time()和permissions(),copy()不做这事 - Windows 下对只读文件复制会失败,需先
permissions(path, perms::owner_write)再操作
路径拼接别用字符串加号,用 std::filesystem::path / 运算符
"a/b" + "/c" 得到 "a/b/c" 是巧合;实际中 "a\b" + "/c" 在 Windows 上会破坏路径结构。C++17 的 std::filesystem::path 重载了 /,它会自动适配平台分隔符并处理冗余 /、.、..。
- 正确写法:
auto p = std::filesystem::path{"a"} / "b" / ".." / "c"→ 解析后是"a/c" - 错误写法:
std::string{"a/b"} + "/c",在 MinGW 或某些 MSVC 设置下可能生成非法路径 -
path.append()和+=也安全,但语义不如/直观;concat()是拼裸字符串,慎用
遍历目录用 std::filesystem::directory_iterator,但注意异常和循环变量生命周期
迭代器不是范围 for 的“值语义”友好类型——它内部持有打开的句柄,若提前销毁(比如在 lambda 中存引用、或在 for 循环外保存 iterator),下次 dereference 就 UB。另外,默认构造的 directory_iterator{} 是 end 迭代器,但 operator!= 不保证短路,最好显式比较。
- 安全写法:
for (const auto& entry : std::filesystem::directory_iterator{dir}) { ... } - 避免:
auto it = directory_iterator{dir}; ++it;后再用,除非你确保it生命周期覆盖所有访问 - 遇到权限拒绝(如子目录不可读),默认抛异常;改用
directory_iterator{dir, ec}并检查ec,否则整个遍历中断 - 需要深度遍历?用
recursive_directory_iterator,但它比普通版慢 2–3 倍(尤其小文件多时),且不能中途跳过子树——得靠disable_recursion_pending()
status() 和 symlink_status() 的区别。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










