C++ Recursive Directory Search Under Linux

I was trying to search for some code examples on how to do a recursive directory search under Linux using C++ the other day. But to my surprise, I could not find any place that offers a complete example. So I decided to post my code here after I created my own and hopefully you will find it helpful.

For those who are impatient, the function to perform recursive directory search is here:

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>
#include <boost/regex.hpp>

void GetFileListing(vector<string> &files, string dir, string filter, bool ignoreCase) {
    DIR *d;
    if ((d = opendir(dir.c_str())) == NULL) return;
    if (dir.at(dir.length() - 1) != '/') dir += "/";

    struct dirent *dent;
    struct stat st;
    boost::regex exp;

    if (ignoreCase)
        exp.set_expression(filter, boost::regex_constants::icase);
    else
        exp.set_expression(filter);

    while ((dent = readdir(d)) != NULL) {
        string path = dir;

        if (string(dent->d_name) != "." && string(dent->d_name) != "..") {
            path += string(dent->d_name);
            const char *p = path.c_str();
            lstat(p, &st);

            if (S_ISDIR(st.st_mode)) {
                GetFiles(files, (path + string("/")).c_str(), filter, ignoreCase);
            } else {
                if (filter == ".*") {
                    files.push_back(path);
                } else {
                    if (boost::regex_match(string(dent->d_name), exp)) files.push_back(path);
                }
            }
        }
    }

    closedir(d);
}

I used boost library to perform regular expression matches for file names. If you just want to obtain a listing of all the files, you can do without using the boost library.

The following code snippet demonstrates how to use the function. The results are stored in a vector container passed in. Note that the “filter” parameter needs standard regular expressions (so if you are looking for any files, the expression should be .* instead of just *) to work properly.

The code should be pretty self-explanatory. If ignoreCase is set to true, then the match will be case-insensitive.

vector<string> files;
    
FileUtils::GetFiles(files,"/tmp", ".*", true);
for (int i = 0 ; i < files.size(); i++) {
    cout << files[i] << endl;
}
Be Sociable, Share!

2 Comments

  1. Daz says:

    and if I wanted a non-recursive version, is there a simple way to disable that in the code above? cheers ;-)

Leave a Reply to Daz