Search code examples
c++c++17boost-filesystemstd-filesystem

iterating through all the directories and subdirectories in c++


I wanted to use the std::filesystem::recursive_directory_iterator class to create a class method iterating through all subdirectories and processing found xml files.

The only way I have found on the internet to do this was using a for loop like this:

for (fs::directory_entry p : fs::recursive_directory_iterator("my_file"))
    do_something(p);

The problem is that i need to store my iterator (or atleast where it's pointing) inbetween function calls as i can only process one file at a time. I tried implementing it like this:

class C {
private:
    std::filesystem::recursive_directory_iterator it;
    std::filesystem::directory_entry p;
public:
    C(std::filesystem::path);
    std::string find_file();
};

C::C(std::filesystem::path path)
{
    it = fs::recursive_directory_iterator(path);
    p = fs::directory_entry(it.begin());
}

std::string C::find_file()
{
    do { //using do while so my function won't load the same file twice
        ++p;
    } while (!is_xml(p.path()) && p != it.end());

}

But it seems that std::filesystem::recursive_directory_iterator doesn't have begin() and end() methods and can't be compared.

I have no idea how my code is different from the working for range loop except for storing the iterator and having an extra condition.


Solution

  • If you look a std::filesystem::recursive_directory_iterator Non-member functions you can see that there is:

    // range-based for loop support
    begin(std::filesystem::recursive_directory_iterator)
    end(std::filesystem::recursive_directory_iterator)
    

    And then std::filesystem::begin(recursive_directory_iterator), std::filesystem::end(recursive_directory_iterator) with more details:

    end(recursive_directory_iterator) Returns a default-constructed recursive_directory_iterator, which serves as the end iterator. The argument is ignored.

    So you will check if it is not equal to std::end(it), so see if there are any more elements. And you have to increment it and not p.

    You also need to check if it != std::end(it) before you do !is_xml(*it.path())

    std::string C::find_file()
    {
        do { //using do while so my function won't load the same file twice
    
            ++it;
        } while (it != std::end(it) && !is_xml(*it.path()));
    
    }