c++oding="utf-8" ?>
recursive_directory_iterator默认跳过符号链接,需显式传follow_directory_symlink选项才能遍历其目标;应捕获filesystem_error避免崩溃,并注意Windows长路径和权限问题。

recursive_directory_iterator 会跳过符号链接,需要显式启用
默认情况下 std::filesystem::recursive_directory_iterator 不遍历符号链接指向的目标,而是直接跳过——这常导致你以为“漏文件”了。比如在 macOS 或 Linux 下用 ln -s 创建的链接,或 Windows 的 junction / symlink,都不会被进入。
解决办法是传入 std::filesystem::directory_options::follow_directory_symlink 标志:
for (auto it = std::filesystem::recursive_directory_iterator(path,
std::filesystem::directory_options::follow_directory_symlink);
it != std::filesystem::recursive_directory_iterator(); ++it) {
if (is_regular_file(it->status())) {
std::cout path()
- 不加标志时,
it->is_symlink()可能返回 true,但迭代器不会递归进去 - 加了标志后,若链接指向的是目录,就会继续向下遍历;若指向文件,则只算作一个叶节点
- Windows 上需确保程序有权限读取目标路径,否则抛
std::filesystem::filesystem_error
遍历时崩溃?检查 path 是否为有效目录且未被删除
常见崩溃场景:迭代中途另一个线程/进程删掉了某子目录,或当前用户权限突然变化(如 NFS 挂载断开),此时 ++it 可能抛异常或触发未定义行为。
安全做法是捕获异常并跳过有问题的条目:
std::filesystem::recursive_directory_iterator it(path);
std::filesystem::recursive_directory_iterator end;
while (it != end) {
try {
if (is_regular_file(it->status())) {
process(it->path());
}
++it;
} catch (const std::filesystem::filesystem_error& e) {
// e.code().message() 可能是 "Permission denied" 或 "No such file or directory"
++it; // 尝试继续,避免卡死
}
}
- 不要在 catch 块里直接 return 或 break,否则整个遍历提前终止
- 某些旧版 libstdc++(GCC
- macOS 上 HFS+ 卷可能返回重复路径(因硬链接或 APFS 克隆),需用
it->path().lexically_normal()去重
想按修改时间排序?别在遍历中 sort,先收集再排
recursive_directory_iterator 是前序深度优先遍历,天生无序。如果边遍历边插入 std::set 或调用 std::sort,性能会极差——因为每次插入都要比较完整路径字符串,且磁盘 I/O 和路径解析开销叠加。
更合理的做法是先存路径 + 元数据,再统一排序:
std::vector<:pair std::filesystem::path>> files;
for (const auto& entry : std::filesystem::recursive_directory_iterator(path)) {
if (is_regular_file(entry.status())) {
try {
files.emplace_back(entry.last_write_time(), entry.path());
} catch (...) { /* 忽略无法获取时间的文件 */ }
}
}
std::sort(files.begin(), files.end(),
[](const auto& a, const auto& b) { return a.first > b.first; }); // 新的在前</:pair>
- 避免在循环内调用
last_write_time()多次——它可能触发额外系统调用;一次取完存好 - Windows FAT32 卷的时间精度只有 2 秒,
file_time_type比较时注意相等情况 - 如果只关心最近 N 个文件,用
std::partial_sort或堆(std::priority_queue)更省内存
Windows 下长路径报错:\? 前缀不是万能的
即使你用了 \?C:... 前缀,recursive_directory_iterator 仍可能在深层嵌套路径(>260 字符)处失败,尤其当某中间目录名本身超长,或包含非法字符(如 CON, AUX)时。
关键点在于:\? 只绕过 Win32 API 层的路径长度限制,但不解决 NT 内核层的校验逻辑。真正稳妥的做法是:
- 编译时开启 long path 支持(Windows 10 1607+):在 manifest 中添加
true - 运行时用
SetThreadErrorMode(SEM_FAILCRITICALERRORS)防止弹框中断遍历 - 遇到
ERROR_INVALID_NAME时,跳过该 entry 并记录日志,而不是让整个迭代器失效
跨平台项目里,别依赖 \? —— 它在 Linux/macOS 下是无效路径,std::filesystem 会直接报错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











