Table of Contents

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 <string>
#include <iostream>
#include <filesystem>
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 <windows.h>
#include <tchar.h>
#include <stdio.h>
 
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 <Windows.h>
 
vector<string> get_all_files_names_within_folder(string folder)
{
    vector<string> 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 <glob.h>
#include <vector>
using std::vector;
 
vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}

NOTE: Can then be called with a normal system wildcard pattern such as:

vector<string> files = globVector("./*");

Using C++11 and Boost

#include <string>
#include <iostream>
#include <boost/filesystem.hpp>
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 <list>
#include <vector>
#include <string>
 
// Collect all files in a directory recursively.
// Filter files, if extensionList contains entries, e. g. {".cpp", ".exe"}
std::list<std::string> get_files_recursively(std::string path, std::vector<std::string> extensionList={});

get_files_recursively.cpp

#include "get_files_recursively.hpp"
#include <filesystem>
 
#if __cplusplus > 201402L
namespace fs = std::filesystem;
#else
namespace fs = std::experimental::filesystem;
#endif
 
 
std::list<std::string> get_files_recursively(std::string basePath, std::vector<std::string> extensionList)
{
  std::list<std::string> 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