简体   繁体   中英

How do I list subdirectories in Windows using C++?

how do I list subdirectories in windows using C++? Using code that would run cross-platorm is better.

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) == FILE_ATTRIBUTE_DIRECTORY
                && (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("\\"));
    }
}

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.

Look at Boost.Filesystem . It's cross-platform and free.

You can use the dirent bib. More details are here

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM