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?
Asked
Active
Viewed 1.1e+01k times
67
-
7[`boost::filesystem`](http://www.boost.org/doc/libs/1_41_0/libs/filesystem/doc/index.htm) is good with files. – chris Jun 21 '12 at 14:33
-
1Writing C++ after Python must feel like writing in an assembly language after C++ :) As far as the standard C++ is concerned, this is a surprisingly code-intensive task. I second the suggestion of using `boost::filesystem`. – Sergey Kalinichenko Jun 21 '12 at 14:36
6 Answers
76
#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;
}
-
3
-
2The only thing that didn't work for me is the 'and', I replaced it by '&&'. The rest is excellent. +1 – Jav_Rock Jul 24 '14 at 11:57
-
12Note: for the extension don't forget to add a dot...for example ".jpg" is the correct, not "jpg". – Silex Jul 13 '15 at 18:48
-
@Jav_Rock You're likely using VS and have to include
to get non-symbol logical operators. – Kaz Dragon Sep 17 '15 at 06:28 -
1
-
-
1Also note that this code only provides the filenames (i.e. without the full path to the file). Should you desire the full path, remove the `.filename()` call. Otherwise, this code works great. Thanks! – rayryeng Mar 28 '20 at 05:16
53
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;
}

1201ProgramAlarm
- 32,384
- 7
- 42
- 56

cck
- 703
- 6
- 11
-
1I'm surprised this was below the other non-cross-platform, non-STL solutions! The only other improvements that could be made are using `std::endl` or making 'p' a `const` variable. – Raleigh L. Nov 04 '21 at 19:08
-
3@RaleighL. `std::endl` is a risky pessimisation since it's in a loop. \n is more correct by default – v.oddou Dec 08 '21 at 07:57
19
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 );
}
}

Rafael Baptista
- 11,181
- 5
- 39
- 59
-
Your solutions would find the file in the pattern, "foo.txt.exe". I wouldn't consider that to have a .txt extension. – Kaz Dragon Sep 17 '15 at 06:48
-
On windows, where are you setting the value of "gIgnoreHidden". Is it a flag? – hshantanu Apr 16 '17 at 15:17
-
yes - its a global boolean in the example. But really you can do anything here - like pass it in as another argument to listFiles. – Rafael Baptista Apr 17 '17 at 13:48
-
On x64 builds from Windows 8 (?) onwards, I believe the hFile should be an intptr_t rather than a long. Using long will result in badness when _findnext is called. – Kaitain May 02 '17 at 21:41
-
For Posix, what are the includes needed for opendir, readdir, and closedir? – Naveen Mar 09 '23 at 16:37
5
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++;
}

encoreleeet
- 374
- 2
- 9

sam
- 151
- 3
- 10
-
Wouldn't it be better to return a const vector & from getFIlesList? filesPaths's declaration was missed in your usage example. – Azeroth2b Aug 17 '23 at 12:24
2
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

crashmstr
- 28,043
- 9
- 61
- 79
0
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.