使用recursive_directory_iterator遍历目录出错后如何继续迭代下一项
C++ std::filesystem递归遍历目录通用错误处理方案
原代码问题分析
你当前把try-catch包裹在整个范围for循环外层,一旦递归目录迭代器在构造或自动递进时抛出异常,就会直接跳出整个循环,无法恢复迭代流程。范围for的底层是自动调用迭代器的operator++,这一步的异常没法在循环内部单独捕获,因此必须改用手动控制迭代的写法。
通用解决方案
你已知的std::filesystem::directory_options::skip_permission_denied仅能处理权限拒绝类错误,其他类型的错误仍会触发异常,以下两种方案可覆盖所有错误场景,实现出错后跳过对应路径、继续遍历的需求:
方案1:使用不抛异常的error_code重载接口
从根源避免异常抛出,自主处理所有错误场景:
#include <filesystem> #include <iostream> #include <system_error> namespace fs = std::filesystem; int main() { const fs::path myPath = "/your/target/path"; std::error_code ec; // 构造迭代器时传入ec,构造失败不会抛异常 auto it = fs::recursive_directory_iterator(myPath, ec); const auto end = fs::recursive_directory_iterator(); while (it != end) { if (ec) { std::cout << "遍历出错: " << ec.message() << " 出错路径: " << it->path() << std::endl; // 跳过当前出错的子目录,继续遍历上层其他条目 it.pop(ec); ec.clear(); continue; } // 正常处理当前目录条目 std::cout << *it << std::endl; // 迭代器递进时传入ec,递进失败不会抛异常 it.increment(ec); } return 0; }
方案2:异常处理模式
如果更习惯用异常逻辑处理错误,可把try-catch放到迭代递进的步骤中:
#include <filesystem> #include <iostream> namespace fs = std::filesystem; int main() { const fs::path myPath = "/your/target/path"; // 处理根路径构造迭代器失败的异常 try { auto it = fs::recursive_directory_iterator(myPath); const auto end = fs::recursive_directory_iterator(); while (it != end) { try { std::cout << *it << std::endl; ++it; } catch (const fs::filesystem_error& e) { std::cout << "遍历出错: " << e.what() << std::endl; // 跳过当前出错路径,继续遍历后续条目 std::error_code pop_ec; it.pop(pop_ec); } } } catch (const fs::filesystem_error& e) { std::cout << "根路径访问失败: " << e.what() << std::endl; } return 0; }
迭代器常见报错原因
权限问题不是该迭代器报错的唯一原因,常见触发错误的场景还包括:
- 遍历过程中目标目录/文件被删除、移动
- 磁盘IO故障、读取失败
- 路径实际为非目录类型(普通文件、设备文件、管道等)
- 特殊虚拟文件系统的动态路径无法读取(比如Linux下
/proc、/sys目录下的部分动态生成路径) - 文件名编码不符合当前系统的编码规范
内容的提问来源于stack exchange,提问作者xx9000
相关产品推荐
相关产品推荐

