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:我只是想指出一点事实上,从你的答案中学到了很多!