====== C - C++ - Files - Get Files in a Directory ====== ===== Using C++17 ===== In C++17 there is now an official way to list files of your file system: std::filesystem: #include #include #include namespace fs = std::filesystem; int main() { std::string path = "/path/to/directory"; for (const auto & entry : fs::directory_iterator(path)) std::cout << entry.path() << std::endl; } ---- ===== Using dirent.h ===== Also available for windows. DIR *dir; struct dirent *ent; if ((dir = opendir ("c:\\src\\")) != NULL) { /* print all the files and directories within directory */ while ((ent = readdir (dir)) != NULL) { printf ("%s\n", ent->d_name); } closedir (dir); } else { /* could not open directory */ perror (""); return EXIT_FAILURE; } ---- ===== Using Boost ===== Cross platform boost method. bool find_file(const path & dir_path, // in this directory, const std::string & file_name, // search for this name, path & path_found) // placing path here if found { if (!exists(dir_path)) return false; directory_iterator end_itr; // default construction yields past-the-end for (directory_iterator itr(dir_path); itr != end_itr; ++itr) { if (is_directory(itr->status())) { if (find_file(itr->path(), file_name, path_found)) return true; } else if (itr->leaf() == file_name) // see below { path_found = itr->path(); return true; } } return false; } ---- ===== For Unix/Linux based systems ===== len = strlen(name); dirp = opendir("."); while ((dp = readdir(dirp)) != NULL) if (dp->d_namlen == len && !strcmp(dp->d_name, name)) { (void)closedir(dirp); return FOUND; } (void)closedir(dirp); return NOT_FOUND; ---- ===== For a windows based systems ===== #include #include #include void _tmain(int argc, TCHAR *argv[]) { WIN32_FIND_DATA FindFileData; HANDLE hFind; if( argc != 2 ) { _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]); return; } _tprintf (TEXT("Target file is %s\n"), argv[1]); hFind = FindFirstFile(argv[1], &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf ("FindFirstFile failed (%d)\n", GetLastError()); return; } else { _tprintf (TEXT("The first file found is %s\n"), FindFileData.cFileName); FindClose(hFind); } } or #include vector get_all_files_names_within_folder(string folder) { vector names; string search_path = folder + "/*.*"; WIN32_FIND_DATA fd; HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd); if(hFind != INVALID_HANDLE_VALUE) { do { // read all (real) files in current folder // , delete '!' read other 2 default folder . and .. if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { names.push_back(fd.cFileName); } }while(::FindNextFile(hFind, &fd)); ::FindClose(hFind); } return names; } ---- ===== C-only ===== tinydir_dir dir; tinydir_open(&dir, "/path/to/dir"); while (dir.has_next) { tinydir_file file; tinydir_readfile(&dir, &file); printf("%s", file.name); if (file.is_dir) { printf("/"); } printf("\n"); tinydir_next(&dir); } tinydir_close(&dir); **NOTE:** Some advantages over other options: * It's portable - wraps POSIX dirent and Windows FindFirstFile * It uses readdir_r where available, which means it's (usually) threadsafe * Supports Windows UTF-16 via the same UNICODE macros * It is C90 so even very ancient compilers can use it ---- ===== Using glob ===== #include #include using std::vector; vector globVector(const string& pattern){ glob_t glob_result; glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result); vector files; for(unsigned int i=0;i **NOTE:** Can then be called with a normal system wildcard pattern such as: vector files = globVector("./*"); ---- ===== Using C++11 and Boost ===== #include #include #include using namespace std; using namespace boost::filesystem; int main() { path p("D:/AnyFolder"); for (auto i = directory_iterator(p); i != directory_iterator(); i++) { if (!is_directory(i->path())) //we eliminate directories { cout << i->path().filename().string() << endl; } else continue; } } ---- ===== Recursively collect all files in a directory ===== ==== get_files_recursively.hpp ==== #pragma once #include #include #include // Collect all files in a directory recursively. // Filter files, if extensionList contains entries, e. g. {".cpp", ".exe"} std::list get_files_recursively(std::string path, std::vector extensionList={}); ---- ==== get_files_recursively.cpp ==== #include "get_files_recursively.hpp" #include #if __cplusplus > 201402L namespace fs = std::filesystem; #else namespace fs = std::experimental::filesystem; #endif std::list get_files_recursively(std::string basePath, std::vector extensionList) { std::list result; for (std::string& strExtension : extensionList) { std::transform(strExtension.begin(), strExtension.end(), strExtension.begin(), ::tolower); } for (fs::path currentPath : fs::recursive_directory_iterator(basePath)) { if (is_regular_file(currentPath)) { bool isMatch = extensionList.empty(); if (!isMatch) { std::string currentExtension = currentPath.extension().string(); for (std::string& strExtension : extensionList) { if (currentExtension == strExtension) { isMatch = true; break; } } } if (isMatch) { result.emplace_back(currentPath.string()); } } } return result; } ---- ===== References ===== https://en.cppreference.com/w/cpp/filesystem/recursive_directory_iterator