【发布时间】:2012-01-14 03:57:51
【问题描述】:
我想在vector<string> 中检索遵循此模式的所有匹配路径:
"/some/path/img*.png"
我怎样才能简单地做到这一点?
【问题讨论】:
我想在vector<string> 中检索遵循此模式的所有匹配路径:
"/some/path/img*.png"
我怎样才能简单地做到这一点?
【问题讨论】:
对于 C++17 标准的较新代码,存在 std::filesystem,它可以通过 std::filesystem::directory_iterator 和递归版本实现这一点。您将不得不手动实现模式匹配。例如,C++11 regex 库。这将可移植到任何支持 C++17 的平台。
std::filesystem::path folder("/some/path/");
if(!std::filesystem::is_directory(folder))
{
throw std::runtime_error(folder.string() + " is not a folder");
}
std::vector<std::string> file_list;
for (const auto& entry : std::filesystem::directory_iterator(folder))
{
const auto full_name = entry.path().string();
if (entry.is_regular_file())
{
const auto base_name = entry.path().filename().string();
/* Match the file, probably std::regex_match.. */
if(match)
file_list.push_back(full_name);
}
}
return file_list;
在非 C++17 案例的 boost 中也实现了类似的 API。 std::string::compare() 可能足以找到匹配项,包括多个调用,len 和 pos 参数仅匹配子字符串。
【讨论】:
我的要点是。我在 glob 周围创建了一个 stl 包装器,以便它返回字符串向量并负责释放 glob 结果。效率不是很高,但这段代码更易读,有些人会说更容易使用。
#include <glob.h> // glob(), globfree()
#include <string.h> // memset()
#include <vector>
#include <stdexcept>
#include <string>
#include <sstream>
std::vector<std::string> glob(const std::string& pattern) {
using namespace std;
// glob struct resides on the stack
glob_t glob_result;
memset(&glob_result, 0, sizeof(glob_result));
// do the glob operation
int return_value = glob(pattern.c_str(), GLOB_TILDE, NULL, &glob_result);
if(return_value != 0) {
globfree(&glob_result);
stringstream ss;
ss << "glob() failed with return_value " << return_value << endl;
throw std::runtime_error(ss.str());
}
// collect all the filenames into a std::list<std::string>
vector<string> filenames;
for(size_t i = 0; i < glob_result.gl_pathc; ++i) {
filenames.push_back(string(glob_result.gl_pathv[i]));
}
// cleanup
globfree(&glob_result);
// done
return filenames;
}
【讨论】:
glob.h 是 unix/posix 系统上的系统头文件。它应该与其他标题(例如 stdio.h 等)位于同一位置。
我在Centos6上试过上面的解决方案,发现需要改:
int ret = glob(pat.c_str(), 0, globerr, &glob_result);
(其中“globerr”是一个错误处理函数)
没有明确的 0,我得到“GLOB_NOSPACE”错误。
【讨论】:
前段时间无聊时,我为 Windows 和 Linux 编写了一个简单的 glob 库(可能也适用于其他 *nixes),请随意使用它。
示例用法:
#include <iostream>
#include "glob.h"
int main(int argc, char **argv) {
glob::Glob glob(argv[1]);
while (glob) {
std::cout << glob.GetFileName() << std::endl;
glob.Next();
}
}
【讨论】:
您可以使用glob() POSIX 库函数。
【讨论】:
char** 而不是 std::vector<std::string> 等)。但它仍然是使用 C++ 编程时使用的正确函数。编写一个提供“C++ 风格”接口的包装器也应该相当容易。