Recursive function to list all files in subdirectories

I am trying to write a function that returns a list of all the files in the current folder and all its subfolders. I wrote this code:

#include <iostream> #include <dirent.h> #include <cstring> using namespace std; int main() { DIR* dir; dirent* pdir; //From my workspace dir=opendir("."); while (pdir=readdir(dir)) { if(/**********This pdir is a directory**********/) { /**********RECURSIVE CALL SHOULD BE HERE**********/ cout<<pdir->d_name<<endl; } } closedir(dir); return 0; } 

I searched for it on google and I don't know how:

  • Check if current pdir directory is
  • Go to the directory and make a recursive call

Meanwhile, I have everything, because I still do not know what arguments a recursive function should have.

Any clues?

+8
source share
7 answers

Isolate this code in a procedure that takes the base directory path as a parameter, so you can actually make a recursive call. It should be something like

 void recursive_file_list(const char * directory) { // ... } 

Then, to check if the pdir directory found is, you have two routes:

  • you can check if pdir->d_type==DT_DIR ; it gives you this information immediately but is not portable (POSIX does not indicate the existence of the d_type member); In addition, it is not supported for all file systems, so you can get DT_UNKNOWN . If you want to follow symbolic links, you also need to do additional checks if you get DT_LNK . In these cases, you should return to lstat (see paragraph below);
  • instead, you can use lstat to use information about each file, checking, in particular, the st_mode struct stat field.
+5
source

Here is the version using the standard file system 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"; } 
+9
source

If 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 calling one function:

 std::copy( boost::filesystem::recursive_directory_iterator("./"), boost::filesystem::recursive_directory_iterator(), std::ostream_iterator<boost::filesystem::directory_entry>(std::cout, "\n")); 
+8
source

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); } } 

Using:

 listFiles("my_directory/", [](const std::string &path) { std::cout << path << std::endl; }); 
+2
source

The path should look like /your_path/ . To search inside hidden folders, you must add the third parameter true .

 #include <dirent.h> #include <vector> #include <cstring> void GetReqDirs(const std::string& path, std::vector<string>& files,const bool showHiddenDirs = false){ DIR *dpdf; struct dirent *epdf; dpdf = opendir(path.c_str()); if (dpdf != NULL){ while ((epdf = readdir(dpdf)) != NULL){ if(showHiddenDirs ? (epdf->d_type==DT_DIR && string(epdf->d_name) != ".." && string(epdf->d_name) != "." ) : (epdf->d_type==DT_DIR && strstr(epdf->d_name,"..") == NULL && strstr(epdf->d_name,".") == NULL ) ){ GetReqDirs(path+epdf->d_name+"/",files, showHiddenDirs); } if(epdf->d_type==DT_REG){ files.push_back(path+epdf->d_name); } } } closedir(dpdf); } 
+1
source

You can check if "." in line.

 if(strstr(pdir->d_name,".") != NULL) 
0
source

Using C ++ 17 recursive_directory_iterator, it becomes as compressed as:

 void ls_recursive(const std::filesystem::path& path) { for(const auto& p: std::filesystem::recursive_directory_iterator(path)) { if (!std::filesystem::is_directory(p)) { std::cout << p.path() << '\n'; } } } 

With an example output:

 "/home/user/prj/rust/stack/Cargo.toml" "/home/user/prj/rust/stack/.gitignore" "/home/user/prj/rust/stack/src/main.rs" "/home/user/prj/rust/stack/.git/config" 
0
source

All Articles