I'm trying to recursively search through directories and pull out any files or subdirectories.

This is the code I have:

int readDir(string directory, vector<string> &fileList) 
//directory is the name of a direcotry 
//fileList is an empty vector

DIR *dir;
struct dirent *ent;

if((dir = opendir(director.c_str()) == NULL){
     cout<<"Invalid Directory"<<endl;
     exit(1);
}
while((ent = readdir(dir)) != NULL){
     fileList.push_back(string(ent->d_name));
}
closedir(dir);
return 0;
}

As of right now, it can read in a directory and list the files and subdirectories. I want it to now go through each subdirectory and get the files inside. Does anyone know how to go about making this a recursive function???

Dani AI

Generated

A few practical, focused notes that fill gaps in the thread and make a recursive directory walker robust and portable.

First, the immediate problem in 's snippet is a misplaced parenthesis and a typo: the result of opendir() must be assigned to the DIR* and then compared to NULL, and the parameter name should be directory not director. Also remember to skip the . and .. entries before recursing — otherwise you’ll loop back to the same directory.

Detection and safety: only recurse when the entry is an actual directory. On POSIX you can test dirent->d_type == DT_DIR when available, but that field can be DT_UNKNOWN on some file systems, so use stat()/lstat() and S_ISDIR() for portability. Use lstat() if you need to detect symlinks; to avoid infinite cycles caused by symbolic links either do not follow directory symlinks, or track visited inodes (device + inode) and skip repeats.

Modern, cross-platform alternative: prefer C++17’s filesystem API where available — it is simpler and handles many edge cases. For example:

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

std::vector<std::string> files;
for (auto &entry : fs::recursive_directory_iterator(path))
    files.push_back(entry.path().string());

This is safer and portable; older compilers without full C++17 filesystem support may need Boost.Filesystem or specific linker flags on legacy toolchains.

Notes on suggestions already posted: ’s popen/ls or dir approach can work for quick scripts but is platform-dependent, brittle to parsing issues, and risky with untrusted input. ’s DirTraveler shows workable recursion; hardening steps are to check opendir() return values, use stat instead of relying on d_type, avoid expensive per-entry allocations (reuse buffers or reserve the vector), and handle permission errors and very deep trees (iterative traversal or an explicit stack if stack depth is a concern).

Checklist: fix the opendir assignment/typo, skip ./.., detect directories portably, decide how to treat symlinks, prefer std::filesystem when possible, and always handle errors (errno) and permission failures.

How about you use code tags and post code that can be compiled.

There are easier ways to get file listings by using the OS list functions & _popen(). The output can be read using fread(). In windows: "dir /s/b ", in Linux: you could try "ls -R -l ".

commented: What can he learn by using "dir /s/b" -3

When you read a file that's a directory, call the function again. And learn to use
CODE tags. There are at least 6 places on the site they are explained.

Usage:

DirTraveler traveler;
vector<string>foo;
traveler.travelDirectoryRecursive("bar", &foo);
for (int i=0; i<foo.size(); ++i)
    cout << foo[i].c_str() << endl;

DirTraveler.h

#ifndef DIRTRAVELER_H
#define DIRTRAVELER_H

#include <string>
#include <vector>

using namespace std;

/// Directory traveler (mostly used with zgui manager)

class DirTraveler
{
    public:
        DirTraveler();
        virtual ~DirTraveler();

        vector<string> travelDirectory(string directory);
        void travelDirectoryRecursive(string directory, vector<string> *fullList);
    protected:
    private:
};

#endif // DIRTRAVELER_H

DirTraveler.cpp

#include "DirTraveler.h"
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <sys/types.h>
#include <dirent.h>
#include <vector>

using namespace std;

DirTraveler::DirTraveler()
{
    //ctor
}

DirTraveler::~DirTraveler()
{
    //dtor
}

vector<string> DirTraveler::travelDirectory(string directory)
{
    // travel thru a directory gathering all the file and directory naems
    vector<string> fileList;
    DIR *dir;
    struct dirent *ent;

    // open a directory
    if ((dir=opendir(directory.c_str())) != NULL)
    {
        while((ent=readdir(dir)) != NULL) // loop until the directory is traveled thru
        {
            // push directory or filename to the list
            fileList.push_back(ent->d_name);
        }
        // close up
        closedir(dir);
    }
    //return the filelust
    return fileList;
}

void DirTraveler::travelDirectoryRecursive(string directory, vector<string> *fullList)
{
    // get the "root" directory's directories
    vector<string> fileList = travelDirectory(directory);

    // loop thru the list
    for (vector<string>::iterator i=fileList.begin(); i!=fileList.end(); ++i)
    {
        // test for . and .. directories (this and back)
        if (strcmp((*i).c_str(), ".") &&
            strcmp((*i).c_str(), ".."))
        {
            // i use stringstream here, not string = foo; string.append(bar);
            stringstream fullname;
            fullname << directory << "/" << (*i);

            fullList->push_back(fullname.str());

            travelDirectoryRecursive(fullname.str(), fullList);
        }
    }
}
commented: why did you post this? -7
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.