Reputation: 776
how do I list subdirectories in windows using C++? Using code that would run cross-platorm is better.
Upvotes: 11
Views: 22724
Reputation: 776
Here's my solution for the problem, it is a Windows only solution though. I want to use a cross-platform solution, but not using boost.
#include <Windows.h>
#include <vector>
#include <string>
/// Gets a list of subdirectories under a specified path
/// @param[out] output Empty vector to be filled with result
/// @param[in] path Input path, may be a relative path from working dir
void getSubdirs(std::vector<std::string>& output, const std::string& path)
{
WIN32_FIND_DATA findfiledata;
HANDLE hFind = INVALID_HANDLE_VALUE;
char fullpath[MAX_PATH];
GetFullPathName(path.c_str(), MAX_PATH, fullpath, 0);
std::string fp(fullpath);
hFind = FindFirstFile((LPCSTR)(fp + "\\*").c_str(), &findfiledata);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if ((findfiledata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0
&& (findfiledata.cFileName[0] != '.'))
{
output.push_back(findfiledata.cFileName);
}
}
while (FindNextFile(hFind, &findfiledata) != 0);
}
}
/// Gets a list of subdirectory and their subdirs under a specified path
/// @param[out] output Empty vector to be filled with result
/// @param[in] path Input path, may be a relative path from working dir
/// @param[in] prependStr String to be pre-appended before each result
/// for top level path, this should be an empty string
void getSubdirsRecursive(std::vector<std::string>& output,
const std::string& path,
const std::string& prependStr)
{
std::vector<std::string> firstLvl;
getSubdirs(firstLvl, path);
for (std::vector<std::string>::iterator i = firstLvl.begin();
i != firstLvl.end(); ++i)
{
output.push_back(prependStr + *i);
getSubdirsRecursive(output,
path + std::string("\\") + *i + std::string("\\"),
prependStr + *i + std::string("\\"));
}
}
Upvotes: 8
Reputation: 1360
in 2022 onwards use
std::filesystem::directory_iterator
for example:
#include <filesystem>
using namespace std::filesystem;
path sandbox = "sandbox";
create_directories(sandbox/"dir1"/"dir2");
// directory_iterator can be iterated using a range-for loop
for (auto const& dir_entry : directory_iterator{sandbox}){
if(dir_entry.is_directory()){ //checking if dir or file.
std::cout << dir_entry << '\n';
}
}
Keep in mind that there is also
std::filesystem::recursive_directory_iterator
which is used for traversing nested subdirectories, all in one go.
https://en.cppreference.com/w/cpp/filesystem/directory_iterator
Upvotes: 5
Reputation: 592
Here's a relatively good solution that should work cross platform. You'll have to change the section of the code where you want it to do something but otherwise it should work quite well.
#include <cstring>
#include <io.h>
#include <iostream>
#include <stdio.h>
using namespace std;
void list(char* dir)
{
char originalDirectory[_MAX_PATH];
// Get the current directory so we can return to it
_getcwd(originalDirectory, _MAX_PATH);
_chdir(dir); // Change to the working directory
_finddata_t fileinfo;
// This will grab the first file in the directory
// "*" can be changed if you only want to look for specific files
intptr_t handle = _findfirst("*", &fileinfo);
if(handle == -1) // No files or directories found
{
perror("Error searching for file");
exit(1);
}
do
{
if(strcmp(fileinfo.name, ".") == 0 || strcmp(fileinfo.name, "..") == 0)
continue;
if(fileinfo.attrib & _A_SUBDIR) // Use bitmask to see if this is a directory
cout << "This is a directory." << endl;
else
cout << "This is a file." << endl;
} while(_findnext(handle, &fileinfo) == 0);
_findclose(handle); // Close the stream
_chdir(originalDirectory);
}
int main()
{
list("C:\\");
return 0;
}
This is pretty concise code and will list all sub-directories and files in the directory. If you want to have it list all the contents in each sub-directory, you can recursively call the function by passing in the sub-directory on the line that prints out "This is a directory." Something like list(fileinfo.name); should do the trick.
Upvotes: 4
Reputation: 11572
http://msdn.microsoft.com/en-us/library/aa364418(v=vs.85).aspx
and
http://msdn.microsoft.com/en-us/library/aa365200(v=vs.85).aspx
its crossplatform between windows vista/7 or maybe xp :P
Upvotes: 4