通过当前,然后父目录递归迭代以查找子目录

时间:2015-04-14 08:38:28

标签: recursion boost siblings c++03 boost-filesystem

我想使用boost::filesystem来查找某个名称的目录。 搜索的开始应该是当前目录。如果我要查找的目录不存在,我需要搜索父目录,依此类推。 应搜索3个目录级别。 但是,我的代码似乎确实陷入了循环。 boost可以提供更方便的解决方案吗?

for (boost::filesystem::directory_iterator Itr(boost::filesystem::current_path()); oItr != oEndItr; ++oItr)
{
 if (!boost::filesystem::is_directory(oItr->status()))
        continue;
 if (oItr->path().filename().string() != "DirectoryName")
 {
        if (oItr == oEndItr)
            oItr = boost::filesystem::directory_iterator(oItr->path().parent_path());
        continue;
    }
 //Found the directory!
}

2 个答案:

答案 0 :(得分:2)

您需要一个树递归算法来跟踪已经访问过的目录。

您应该为此目的规范化路径,或使用(device,inode)组合来检查访问状态。这是为了避免循环(sym)链接循环或同名的不同拼写。

在我的简单例子中:

for (fs::path current : { ".", "..", "../..", "../../../" }) {
    auto const& sub = recurse(fs::canonical(current));
    if (!sub.empty())
        return sub;
}

它也解释了例如../..../../../引用同一目录(/)。

演示输出:

mkdir -p haystack/{a..z}/sub/{1..10} haystack/j/sub/9/needle
g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp -lboost_system -lboost_filesystem -o test
cd haystack/k/sub/4 && ../../../../test
FOUND "/tmp/1429002953.62583/haystack/j/sub/9/needle"

Live On Coliru Live On Coliru (c++03)

#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <functional>
#include <set>
#include <iostream>

namespace fs = boost::filesystem;

fs::path find_directory(std::string const& name) {
    std::set<fs::path> visited;

    std::function<fs::path(fs::path const&)> recurse;
    recurse = [&visited, &name, &recurse](fs::path const& dir) -> fs::path {
        if (visited.insert(dir).second) { // not visited already
            try {
                for (auto& de : boost::make_iterator_range(fs::directory_iterator(dir), {})) {
                    if (fs::is_directory(de))
                    {
                        if (de.path().filename() == name)
                            return de.path();

                        // TODO check accessibility?
                        auto const& sub = recurse(de.path());

                        if (!sub.empty())
                            return sub;
                    }
                }
            } catch(fs::filesystem_error& e) {
                std::cerr << "Error: " << e.what() << "\n";
            }
        }
        return {};
    };

    for (fs::path current : { ".", "..", "../..", "../../../" }) {
        auto const& sub = recurse(fs::canonical(current));
        if (!sub.empty())
            return sub;
    }

    return {};
}

int main() {
    std::cout << "FOUND " << find_directory("needle") << "\n";
}

答案 1 :(得分:1)

为了递归遍历目录和子目录,Boost.Filesystem提供了迭代器boost :: filesystem :: recursive_directory_iterator。

#include <iostream>
#include <boost/filesystem/path.hpp>

using namespace boost::filesystem;

int main(int argc, char** argv)
{    
    path full_path(initial_path<path>());
    full_path = system_complete(path(argv[0]));
    path dir = full_path.parent_path();

    for(recursive_directory_iterator it(dir); it != recursive_directory_iterator() ; it++)
    {
        if (it->path().filename().string() == "DirectoryName")
        {
            std::cout << it->path() << std::endl;
        }
    }

    return 0;
}