我正在尝试使用
std::filesystem::recursive_directory_iterator
迭代我的 C 驱动器并打印文件路径,但我不断遇到以下异常:terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error' what(): filesystem error: cannot increment recursive directory iterator: Invalid argument
我已经尝试过:
#include <iostream>
#include <filesystem>
int main() {
for (auto const& dir_entry : std::filesystem::recursive_directory_iterator("C:\\")) {
try {
std::cout << dir_entry << std::endl;
} catch (std::filesystem::__cxx11::filesystem_error) {
continue;
}
}
return 0;
}
我希望它在遇到异常后继续下一次迭代,但我只是收到了相同的错误消息。
我也尝试过:
#include <iostream>
#include <filesystem>
int main() {
try {
for (auto const& dir_entry : std::filesystem::recursive_directory_iterator("C:\\")) {
std::cout << dir_entry << std::endl;
}
} catch (std::filesystem::__cxx11::filesystem_error) {
std::cout << "Ran into exception";
}
return 0;
}
它捕获了问题并且执行了
catch
块,但我无法继续下一次迭代,因为 try/catch
语句位于 for
循环之外。
您无法继续下一个迭代,因为没有下一个迭代。
无法递增递归目录迭代器
如果出现其他异常,您的第一个代码片段可能会工作,但这个代码片段将不允许迭代继续。
这是一个解决方法。
#include <iostream>
#include <filesystem>
int main(int argc, char** argv)
{
if(argc < 1)
return 1;
for(std::filesystem::recursive_directory_iterator i {argv[1]}, saved, end;
i != end; ) {
const std::filesystem::directory_entry& entry = *i;
std::cout << entry << '\n';
/*
* important: Check symlink first. If it is a symlink and we
* don't have permission to read it, the is_directory check
* may throw filesystem_error
*/
if(! (entry.is_symlink() || entry.is_directory())) { // fast path
++i;
continue;
}
saved = i;
try {
++i;
} catch(std::filesystem::filesystem_error& err) {
std::cout << "Error: " << err.what() << '\n';
i = std::move(saved);
i.disable_recursion_pending();
++i;
}
}
}
基本上,您可以将迭代器保存在副本中,然后禁用递归。问题在于,这相当昂贵,因为迭代器包含其整个递归状态。所以我们只在必要时复制。
skip_permission_denied
标志。但有时您可能想知道是否存在没有权限的目录。那么我认为这是最好的选择。或者,您可以先探测每个目录,而不使用迭代器来查看是否可以读取它,然后根据需要调用 disable_recursion_pending
。