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