Recursive function for listing all files in sub directories
Unless your goal is to learn how to write a recursive function, you might prefer this simple loop based on Boost.Filesystem:
#include "boost/filesystem.hpp"
#include <iostream>
int main () {
for ( boost::filesystem::recursive_directory_iterator end, dir("./");
dir != end; ++dir ) {
// std::cout << *dir << "\n"; // full path
std::cout << dir->path().filename() << "\n"; // just last bit
}
}
Or even the single function call:
std::copy(
boost::filesystem::recursive_directory_iterator("./"),
boost::filesystem::recursive_directory_iterator(),
std::ostream_iterator<boost::filesystem::directory_entry>(std::cout, "\n"));
My approach in C++11:
#include <string>
#include <functional>
#include <dirent.h>
void listFiles(const std::string &path, std::function<void(const std::string &)> cb) {
if (auto dir = opendir(path.c_str())) {
while (auto f = readdir(dir)) {
if (!f->d_name || f->d_name[0] == '.') continue;
if (f->d_type == DT_DIR)
listFiles(path + f->d_name + "/", cb);
if (f->d_type == DT_REG)
cb(path + f->d_name);
}
closedir(dir);
}
}
Usage:
listFiles("my_directory/", [](const std::string &path) {
std::cout << path << std::endl;
});
Here is a version using proposed standard filesystem library:
#include <iostream>
#include <filesystem>
using namespace std;
using namespace std::tr2::sys;
void main()
{
for (recursive_directory_iterator i("."), end; i != end; ++i)
if (!is_directory(i->path()))
cout << i->path().filename() << "\n";
}
Isolate that code in a procedure that takes the base directory path as a parameter, so you can actually perform the recursive call. It should be something like
void recursive_file_list(const char * directory)
{
// ...
}
Then, to check if the pdir
you obtained is a directory, you have two routes:
- you can check if
pdir->d_type==DT_DIR
; this gives you this information immediately, but it's not portable (POSIX does not mandate the existence of thed_type
member); also, it's not supported for all the filesystems, so you may getDT_UNKNOWN
. If you want to follow symlinks, you have to perform extra checks also if you getDT_LNK
. In these cases, you must fall back tolstat
(see the point below); - you can instead portably use
lstat
to get information about each file, checking in particular thest_mode
field ofstruct stat
.