简体   繁体   中英

Find directories and sub-directories through recursion in C++

I want to create a method that reads a directory and finds and saves in a data structure all the directories included, as well as all the sub-directories of each directory. Specifically I want the names to be cited as:

folder1 folder11 folder12 folder2 folder21 folder22 folder23

I need obviously a function with recursion. I use temporary a class member method in a console application as:

private:
 struct dirent *ep;


void DirectoryReader::parseDirectory(char* readingDirectory)
{
char* tempDirectory = (char*)malloc(sizeof(readingDirectory) + 200); 
string temp = readingDirectory;

DIR *dp;
dp = opendir (readingDirectory);
   if (dp != NULL)
     {
       while (ep = readdir (dp))
       {
         puts (ep->d_name);

         temp += readingDirectory;
         temp += "/";
         temp += ep->d_name;

         char * buffer = new char[temp.length()];
         strcpy(buffer,temp.c_str());
         parseDirectory(buffer);
       }
         (void) closedir (dp);
     }
   else
     perror ("Couldn't open the directory");

}

Ok, I know not the best written code, but I want initially to have a view of the names caught. However it does not work properly, since it considers the name of the parent directory more than once. Even if I put the invocation of the same method out (not performing recursion) the first two names are . and .. . Why?

Could you suggest me a function doing the described process or indicate the correction demanded on this function?

as some comment pointed out, boost::filesystem is the usually way to go. But from your code it seems you are still a newbie to C++, so I've rewritten in C++ idiomatic way, adding a bit of useful display. HTH

#include <dirent.h>
#include <iostream>
#include <string>
using namespace std;

struct DirectoryReader
{
    static void parseDirectory(string readingDirectory, int level);
};

void DirectoryReader::parseDirectory(string readingDirectory, int level)
{
    if (DIR *dp = opendir(readingDirectory.c_str()))
    {
        cout << string(level, ' ') << readingDirectory << endl;
        while (struct dirent *ep = readdir(dp))
            if (ep->d_type == DT_DIR && ep->d_name[0] != '.')
                parseDirectory(readingDirectory + "/" + ep->d_name, level + 1);
        closedir(dp);
    }
    else
        cerr << "Couldn't open the directory " << readingDirectory << endl;
}

int main_parsedir(int argc, char **argv)
{
    if (argc > 1)
        DirectoryReader::parseDirectory(argv[1], 0);
    return 0;
}

note that in your code, storing struct dirent *ep; in class is plain wrong, because you overwrite it while recursing...

Directory enumeration functions usually return the current directory (.) and parent directory (..) links. You need to ignore them. Additionally you need to check for ep->d_type. I have written the following function for you. Please check if this works as expected. I didn't use the space separator for the output since the individual folders can have space character in them. Also, I'm not sure how you are going to use this output since it looses the tree structure.

#include "dirent.h"

const string theDelimiter = "\\";

class DirectoryReader
{
public:
    string DirectoryReader::parseDirectory(string readingDirectory, const string& aCurrentFolderName)
    {
        string aChildren;
        aChildren += theDelimiter;
        aChildren += aCurrentFolderName;

        DIR *dp = opendir (readingDirectory.c_str());
        if (dp != NULL)
        {
            struct dirent *ep = NULL;
            while ((ep = readdir (dp)) && ep->d_type == DT_DIR )
            {
                string aDirName = ep->d_name;

                //  Ignore current directory and the parent directory links
                if(!aDirName.compare(".") || !aDirName.compare(".."))
                    continue;

                //  Form the full directory path
                string aFullFolderName = readingDirectory;
                aFullFolderName += string("\\");
                aFullFolderName += aDirName;

                string aChildrenFolders = parseDirectory(aFullFolderName, aDirName);
                if(aChildrenFolders.compare(""))
                {
                    aChildren += aChildrenFolders;
                }
            }

            (void) closedir (dp);
        }
        else
            perror ("Couldn't open the directory");

        return aChildren;
    }
};

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