如何在c++98中过滤掉结果以仅获取输出结果linux中的文件名

How to filter out the result to get only file names in output result linux in c++98

当前代码片段将匹配模式并列出指定目录中存在的所有匹配模式文件,其中 下面的示例 File 是要匹配的模式*,这里输出将以绝对路径列出,如下所示。

    /home/downloads/File1
    /home/downloads/File2
    /home/downloads/File3
    /home/downloads/File4

其中,我只查找要列出的文件名,如下所示:

File1
File2
File3
File4

c++ 代码如下:

    #include <glob.h>
    #include <cerrno>
    #include <cstring>
    #include <iostream>
    #include <stdexcept>
    #include <string>
    #include <vector>
    using namespace std;
    vector<string> glob(const string& pattern) {
        glob_t glob_result = {0}; // zero initialize
        // do the glob operation
        int return_value = ::glob(pattern.c_str(), GLOB_TILDE, NULL, &glob_result);
        if(return_value != 0) throw runtime_error(strerror(errno));
        // collect all the filenames into a std::vector<std::string>
        // using the vector constructor that takes two iterators
        vector<string> filenames(
            glob_result.gl_pathv, glob_result.gl_pathv + glob_result.gl_pathc);
        // cleanup
        globfree(&glob_result);
        
        // done
        return filenames;
    }
    int main() {
        try { // catch exceptions
               vector<string> res = glob("/home/downloads/File*"); // files with an "File" in the filename
               for(size_t i = 0; i< res.size(); ++i)
                  std::cout << res[i] << '\n';
            } catch(const exception& ex) {
            cerr << ex.what() << endl;
        }
    }

 

有点,可以过滤掉目录。将 GLOB_TILDE 更改为 GLOB_TILDE | GLOB_MARK,如下所示:

vector<string> glob(const string& pattern) {
    glob_t glob_result = {};
    vector<string> filenames;
    try {
        int return_value = ::glob(pattern.c_str(), GLOB_TILDE | GLOB_MARK, NULL, &glob_result);
        if (return_value != 0) {
            throw runtime_error(strerror(errno));
        }
        filenames.reserve(glob_result.gl_pathc);
        for (size_t globIndex = 0; globIndex < glob_result.gl_pathc; ++globIndex) {
            std::string filename = glob_result.gl_pathv[globIndex];
            if (filename.size() > 0 && filename[filename.size() - 1] != '/') {
                filenames.push_back(filename);
            }
        }
    } catch(...) {
        globfree(&glob_result);
        throw;
    }
    // cleanup
    globfree(&glob_result);

    // done
    filenames.shrink_to_fit();
    return filenames;
}

备注:

  • 您仍然需要 stat 每个结果并检查它是否是一个文件。可以是符号链接、设备文件、命名管道 (FIFO)...
  • 代码不是异常安全的,在填充向量时内存可能 运行 耗尽并且您的清理不会发生。使用 try/catch 或类似 scope_exit 的东西(如果可以的话)或编写一个守卫对象并使用它的析构函数。
  • 我不确定你是否应该 globfree 以防出错,但 valgrind 表明这不是问题。