What you want is not fully possible with std::filesystem::recursive_directory_iterator
, even if you write the loop manually.
There are two places where the iterator can throw exceptions1, the de-referencing operator (*it
) and the increment operator (++it
).
If any of these reports an error (i.e., throws an exception in your case), the iterator cannot be used anymore.2
For the de-referencing iterator, you can backup the iterator and skip invalid entries
auto it = std::filesystem::recursive_directory_iterator{md};
while (it != std::filesystem::recursive_directory_iterator{}) {
const auto tmp_it = it;
try {
const auto& path = *tmp_it;
// use path...
}
catch (std::filesystem::filesystem_error const&) {
}
// you can still increment it here
++it;
}
Unfortunately, if the increment operator reports an error (throws or reports an std::error_code
), there is not much you can do to simply "skip" that element — you can handle some cases, but not everything, e.g.
std::error_code ec;
const auto backup = it;
// try increment
it.increment(ec);
// failed
if (ec) {
it = backup;
// the iterator tried to enter a directory and failed, disable the
// recursion for the next entry
if (it.recursion_pending()) {
it.disable_recursion_pending();
// try again
it.increment(ec);
}
}
// still failed, or was not recursion_pending()
if (ec) {
it = backup;
// try to skip the remaining entry at the given depth go back to
// the parent
it.pop(ec);
}
// nothing much you can do here unfortunately
if (ec) {
}
1 The constructor can also report error but in this case you do not even have a valid iterator to begin with so that is not relevant for your question.
2 Standard quotes:
[filesystems#fs.class.directory.iterator.general-3]
If an iterator of type directory_iterator
reports an error or is advanced past the last directory element, that iterator shall become equal to the end iterator value. [..]
[filesystems#fs.class.rec.dir.itr.general-3]
The behavior of a recursive_directory_iterator
is the same as a directory_iterator
unless otherwise specified.