This is a simple example of how to use recursion to get a list of all the directories (folders) and file names within them. It also illustrates simple use if std::list, std::vector, std::string, std::cin and std::cout. It was compiled and tested with both VC++ 6.0 and Dev-C++ compilers on XP Pro.

// The next two lines are for VC++ 6.0 compiler.  You should 
// delete them if you compile it with a different compiler.
#include "stdafx.h"
#pragma warning(disable: 4786)
#include <io.h>
#include <string>
#include <vector>
#include <list>
#include <iostream>
using namespace std;


// structure to hold a directory and all its filenames.
struct FILELIST
{
	string path;
	vector<string> theList;
};


void TransverseDirectory(string path, list<FILELIST>& theList)
{
	struct _finddatai64_t data;
	// First create the filename that will be use to initialize the find.
	// "*.*" are wild card characters that tells the find function to return a 
	// list of all the files and directories.  You can limit this if you wish
	// to just file with specific extensions, for example "*.txt".  If you do that
	// then finder will not return any directory names.
	string fname = path + "\\*.*";
	// start the finder -- on error _findfirsti64() will return -1, otherwise if no
	// error it returns a handle greater than -1.
	long h = _findfirsti64(fname.c_str(),&data);
	if(h >= 0)
	{
		FILELIST thisList;
		// add empty FILELIST structure to the linked list argument
		theList.push_back(thisList);
		// get pointer to the FILELIST just added to the linked list above.
		list<FILELIST>::iterator it = theList.end();
		it--;
		// set current path
		(*it).path = path;
		do {
			if( (data.attrib & _A_SUBDIR) )
			{
				// make sure we skip "." and "..".  Have to use strcmp here because
				// some file names can start with a dot, so just testing for the 
				// first dot is not suffient.
				if( strcmp(data.name,".") != 0 &&strcmp(data.name,"..") != 0)
				{
					// We found a sub-directory, so get the files in it too
					fname = path + "\\" + data.name;
					// recursion here!
					TransverseDirectory(fname,theList);
				}

			}
			else
			{
				// this is just a normal filename.  So just add it to our vector
				(*it).theList.push_back(data.name);

			}
		}while( _findnexti64(h,&data) == 0);
		// close the find handle.  
		_findclose(h);

	}

}

int main(int argc, char* argv[])
{
	list<FILELIST> MyList;
	string path;
	cout << "Enter starting path ... ";
	getline(cin,path);
	TransverseDirectory(path,MyList);
	list<FILELIST>::iterator it;
	// now just display all the files
	for(it = MyList.begin(); it != MyList.end(); it++)
	{
		vector<string>::iterator its;
		for(its = (*it).theList.begin(); its != (*it).theList.end(); its++)
		{
			cout << (*it).path + "\\" + (*its) << endl;
		}

	}
	cin.ignore();
	return 0;
}

Dani AI

Generated

Nice, compact recursive example from — great as a learning/demo. For production or cross-platform code, a few practical updates make traversal safer, simpler, and Unicode/long-path aware.

A modern, concise alternative is to use the C++ standard library filesystem utilities (C++17+), which handle path semantics for you and provide a robust recursive iterator. The pattern below streams results (no huge in-memory lists), skips permission errors, and lets you disable recursion into problematic or symlinked directories:

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main()
{
    fs::path start = "C:\\some\\start\\path";
    for (auto it = fs::recursive_directory_iterator(start, fs::directory_options::skip_permission_denied);
         it != fs::recursive_directory_iterator(); ++it)
    {
        try {
            const fs::directory_entry &de = *it;
            if (de.is_regular_file())
                std::cout << de.path().string() << '\n';
            // if this entry is a symlink-to-directory, avoid descending into it
            if (de.is_directory() && de.is_symlink())
                it.disable_recursion_pending();
        } catch (const fs::filesystem_error&) {
            // skip entries we can't access and avoid descending
            it.disable_recursion_pending();
        }
    }
}

Use of the [std::filesystem] header (C++17) is recommended for portability and clearer semantics. (en.cppreference.com) The iterator above is recursive_directory_iterator and offers disable_recursion_pending() to stop descending into the current entry when needed; you can also pass directory_options to control symlink-following and permission behavior. (cppreference.com)

Watch for Windows specifics: std::filesystem::path uses the native encoding on Windows (wide strings), so choose wstring/u8 conversions or OS APIs when you need exact Unicode output. Paths longer than MAX_PATH need special handling (the \\?\\ prefix or enabling long-path support) per Microsoft guidance. (en.cppreference.com)

Other practical notes: avoid building huge in-memory maps if you only need to process files (stream them). Detect or skip reparse points/junctions to prevent cycles when walking NTFS links. For a simple, shareable snippet, this is a good candidate to move to the Code Snippets area as suggested. (learn.microsoft.com)

Hmm ... I think something like this would be better suited to our Code Snippets section ... thanky very much for the contribution nonetheless!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.