Question

I want to get the file names of all files that have a specific extension in a given folder (and recursively, its subfolders). That is, the file name (and extension), not the full file path. This is incredibly simple in languages like Python, but I'm not familiar with the constructs for this in C++. How can it be done?

Was it helpful?

Solution

#define BOOST_FILESYSTEM_VERSION 3
#define BOOST_FILESYSTEM_NO_DEPRECATED 
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

/**
 * \brief   Return the filenames of all files that have the specified extension
 *          in the specified directory and all subdirectories.
 */
std::vector<fs::path> get_all(fs::path const & root, std::string const & ext)
{
    std::vector<fs::path> paths;

    if (fs::exists(root) && fs::is_directory(root))
    {
        for (auto const & entry : fs::recursive_directory_iterator(root))
        {
            if (fs::is_regular_file(entry) && entry.path().extension() == ext)
                paths.emplace_back(entry.path().filename());
        }
    }

    return paths;
}             

OTHER TIPS

a C++17 code

#include <fstream>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main()
{
    std::string path("/your/dir/");
    std::string ext(".sample");
    for (auto &p : fs::recursive_directory_iterator(path))
    {
        if (p.path().extension() == ext)
            std::cout << p.path().stem().string() << '\n';
    }
    return 0;
}

On windows you do something like this:

void listFiles( const char* path )
{
   struct _finddata_t dirFile;
   long hFile;

   if (( hFile = _findfirst( path, &dirFile )) != -1 )
   {
      do
      {
         if ( !strcmp( dirFile.name, "."   )) continue;
         if ( !strcmp( dirFile.name, ".."  )) continue;
         if ( gIgnoreHidden )
         {
            if ( dirFile.attrib & _A_HIDDEN ) continue;
            if ( dirFile.name[0] == '.' ) continue;
         }

         // dirFile.name is the name of the file. Do whatever string comparison 
         // you want here. Something like:
         if ( strstr( dirFile.name, ".txt" ))
            printf( "found a .txt file: %s", dirFile.name );

      } while ( _findnext( hFile, &dirFile ) == 0 );
      _findclose( hFile );
   }
}

On Posix, like Linux or OsX:

void listFiles( const char* path )
{
   DIR* dirFile = opendir( path );
   if ( dirFile ) 
   {
      struct dirent* hFile;
      errno = 0;
      while (( hFile = readdir( dirFile )) != NULL ) 
      {
         if ( !strcmp( hFile->d_name, "."  )) continue;
         if ( !strcmp( hFile->d_name, ".." )) continue;

         // in linux hidden files all start with '.'
         if ( gIgnoreHidden && ( hFile->d_name[0] == '.' )) continue;

         // dirFile.name is the name of the file. Do whatever string comparison 
         // you want here. Something like:
         if ( strstr( hFile->d_name, ".txt" ))
            printf( "found an .txt file: %s", hFile->d_name );
      } 
      closedir( dirFile );
   }
}

Get list of files and process each file and loop through them and store back in different folder

void getFilesList(string filePath,string extension, vector<string> & returnFileName)
{
    WIN32_FIND_DATA fileInfo;
    HANDLE hFind;   
    string  fullPath = filePath + extension;
    hFind = FindFirstFile(fullPath.c_str(), &fileInfo);
    if (hFind != INVALID_HANDLE_VALUE){
        returnFileName.push_back(filePath+fileInfo.cFileName);
        while (FindNextFile(hFind, &fileInfo) != 0){
            returnFileName.push_back(filePath+fileInfo.cFileName);
        }
    }
}

USE: you can use like this load all the files from folder and loop through one by one

String optfileName ="";        
String inputFolderPath =""; 
String extension = "*.jpg*";
getFilesList(inputFolderPath,extension,filesPaths);
vector<string>::const_iterator it = filesPaths.begin();
while( it != filesPaths.end())
{
    frame = imread(*it);//read file names
        //doyourwork here ( frame );
    sprintf(buf, "%s/Out/%d.jpg", optfileName.c_str(),it->c_str());
    imwrite(buf,frame);   
    it++;
}

You don't say what OS you are on, but there are several options.

As commenters have mentioned, boost::filesystem will work if you can use boost.

Other options are

Here's my solution (works on *nix systems):

#include <dirent.h>

bool FindAllFiles(std::string path, std::string type, std::vector<std::string> &FileList){
  DIR *dir;
  struct dirent *ent;
  FileList.clear();

  if ((dir = opendir (path.c_str())) != NULL) {
    //Examine all files in this directory
    while ((ent = readdir (dir)) != NULL) {
      std::string filename = std::string(ent->d_name);
      if(filename.length() > 4){
        std::string ext = filename.substr(filename.size() - 3);
        if(ext == type){
          //store this file if it's correct type
          FileList.push_back(filename);
        }
      }
    }
    closedir (dir);
  } else {
    //Couldn't open dir
    std::cerr << "Could not open directory: " << path << "\n";
    return false;
  }
  return true;
}

Obviously change the desired extension to whatever you like. Also assumes a 3 character type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top