Recursion 递归遍历当前目录,然后遍历父目录以查找子目录

Recursion 递归遍历当前目录,然后遍历父目录以查找子目录,recursion,boost,siblings,c++03,boost-filesystem,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::filesys

我想使用
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!
}

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

为此,您应该规范化路径,或者使用
(设备,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"

#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";
}
#包括
#包括
#包括
#包括
#包括
名称空间fs=boost::filesystem;
fs::path find_目录(std::string const&name){
std::访问的集合;
函数递归;
recurse=[&visted,&name,&recurse](fs::path const&dir)->fs::path{
if(visited.insert(dir.second){//尚未访问
试一试{
for(auto&de:boost::make_iterator_range(fs::directory_iterator(dir),{})){
if(fs::is_目录(de))
{
if(de.path().filename()==名称)
返回de.path();
//TODO检查可访问性?
auto const&sub=递归(de.path());
如果(!sub.empty())
返回子节点;
}
}
}捕获(fs::文件系统错误&e){

要递归地迭代一个目录和子目录,Boost.Filesystem提供了迭代器Boost::Filesystem::recursive_directory_迭代器

#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;
}
#包括
#包括
使用名称空间boost::filesystem;
int main(int argc,字符**argv)
{    
路径完整路径(初始路径());
完整路径=系统完整(路径(argv[0]);
path dir=完整路径。父路径();
for(递归目录迭代器it(dir);it!=递归目录迭代器();it++)
{
如果(它->路径().filename().string()=“目录名”)
{

std::cout路径()将
oItrEnd
设置为指向子目录后,
oItr
是错误的。但是,即使您在深入时更新了
oEndItr
,您的代码也需要跟踪整个
oEndItr
堆栈,以便运行每个嵌套的目录循环。因此,您可以创建一个堆栈,或者更简单的递归函数n、 它使用“堆栈”,因此您不必创建自己的堆栈。非常感谢!但是您似乎使用的是C++11代码和boost>1.49。这是否正确?我既不能使用
auto
也不能使用以下语法:
{“…”}
@tzippy我不认为您不能使用这些功能会妨碍您了解它们的工作原理,因此如果需要,您可以简单地转换为c++03:。我现在为您重新标记问题。如果您从一开始就告诉我们,@tzippy会很好。很抱歉没有提供这些信息。@sehe:我只是想指出一点事实上,从你的答案中学到了很多!