Traversing a directory with boost::filesystem without throwing exceptions

青春壹個敷衍的年華 提交于 2019-12-05 08:26:01

Ha, figured it out, there is a way:

std::vector<fs::path> traverse_if_directory(fs::path& f) {
    std::vector<fs::path> result;
    boost::system::error_code ec;

    if (fs::is_directory(f)) {      
        for (
             fs::recursive_directory_iterator it(f, ec), eit;
             it != eit;
             it.increment(ec)
            ) {
            if (ec) {
                it.pop();
                continue;
            }
            if (!fs::is_directory(it->path())) {
                result.push_back(it->path());
            }
        }
    }
    else {
        result.push_back(f);
    }

    return result;
}

There is a non-throwing overload which accepts an output parameter of type boost::system::error_code, so I can just check after each increment if there were any error.

Joker_vD's answer crashes when an error occurs for the last directory entry. For example, when the target directory contains a single subdirectory without permissions. The cause is the 'it.pop()' which apparently isn't needed. Also, the 'continue' shouldn't be done, as it would skip the next entry. After an error the iterator already points to the next valid entry, or is equal to the end iterator.

This is a corrected version:

std::vector<fs::path> traverse_if_directory(const fs::path& f) {
    std::vector<fs::path> result;
    boost::system::error_code ec;

    if (fs::is_directory(f)) {
        for (fs::recursive_directory_iterator it{f, ec}, end; it != end; it.increment(ec)) {
            if (!fs::is_directory(it->path())) {
                result.push_back(it->path());
            }
        }
    }
    else {
        result.push_back(f);
    }

    return result;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!