C++ 中的简单 glob在unix系统上?

发布于 2024-12-19 13:58:26 字数 134 浏览 0 评论 0原文

我想检索 vector 中遵循此模式的所有匹配路径:

"/some/path/img*.png"

我怎样才能简单地做到这一点?

I want to retrieve all the matching paths following this pattern in a vector<string>:

"/some/path/img*.png"

How can I simply do that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如果没有 2024-12-26 13:58:26

我的要点是这样的。我创建了一个围绕 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;
}

I have that in my gist. I created a stl wrapper around glob so that it returns vector of string and take care of freeing glob result. Not exactly very efficient but this code is a little more readable and some would say easier to use.

#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;
}
南笙 2024-12-26 13:58:26

您可以使用 glob() POSIX 库函数。

You can use the glob() POSIX library function.

不奢求什么 2024-12-26 13:58:26

我为 Windows 和 Windows 编写了一个简单的 glob 库。 Linux(可能也适用于其他*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();
  }
}

I wrote a simple glob library for Windows & Linux (probably works on other *nixes as well) a while ago when I was bored, feel free to use it as you like.

Example usage:

#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();
  }
}
话少情深 2024-12-26 13:58:26

对于 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() 可能足以查找匹配项,包括多次调用,并使用 lenpos 参数来匹配 sub -仅限字符串。

For newer code to the C++17 standard, std::filesystem exists and it can achieve this with std::filesystem::directory_iterator and the recursive version. You will have to manually implement the pattern matching. For instance, the C++11 regex library. This will be portable to any platform with C++17 support.

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;

A similar API is also implemented in boost for non-C++17 cases. std::string::compare() might be sufficient to find a match, including multiple calls, with len and pos arguments to match sub-strings only.

听风吹 2024-12-26 13:58:26

我已经在 Centos6 上尝试了上面的解决方案,我发现我需要更改:(

int ret = glob(pat.c_str(), 0, globerr, &glob_result);

其中“globerr”是一个错误处理函数)

如果没有显式的 0,我会收到“GLOB_NOSPACE”错误。

I've tried the solutions above on Centos6, and I found out that I needed to change:

int ret = glob(pat.c_str(), 0, globerr, &glob_result);

(where "globerr" is an error handling function)

Without the explicit 0, I got "GLOB_NOSPACE" error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文