Search code examples
c++linuxglobc++98file-globs

How to glob file name pattern matching in linux using c++ 98


Below is the piece of code, where I am trying to find file with matching pattern from directory path provided.

the expectation is to list all the files with pattern matching, for example under "/usr/local" path, the below files are present abc.txt axy.txt bcd.txt azz.txt bby.txt

with pattern matching code, i am expecting the below output

       abc.txt
       axy.txt
       azz.txt
#include <glob.h> 
#include <string.h> 
#include <vector>
#include <stdexcept>
#include <string>
#include <sstream>
#include <iostream>
    
    using namespace std;
    vector<string> glob(const string& pattern) {
    
        // 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(), 0, globerr, &glob_result);
       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;
    }

    int main(int argc, char **argv) {
        vector<string> res;
        res= glob("a");
        return 0;
      }

Solution

  • As mentioned in the comments, you'll only match on a file named exactly a, you globfree when you shouldn't and thrown an exception that you don't catch.

    #include <glob.h>
    
    #include <cerrno>
    #include <cstring>
    #include <iostream>
    #include <stdexcept>
    #include <string>
    #include <vector>
    
    std::vector<std::string> glob(const std::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 std::runtime_error(std::strerror(errno));
    
        // collect all the filenames into a std::vector<std::string>
        // using the vector constructor that takes two iterators
        std::vector<std::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
            std::vector<std::string> res = glob("*a*"); // files with an "a" in the filename
    
            for(size_t i = 0; i< res.size(); ++i)
                std::cout << res[i] << '\n';
    
        } catch(const std::exception& ex) {
            std::cerr << ex.what() << std::endl;
        }
    }