====== 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