tty6
tty6

Reputation: 1233

Invalidation of boost recursive_directory_iterator while removing files inside cycle

I found that boost::recursive_directory_iterator has different behaviour rather than boost::directory_iterator

So I have two structures:

struct directory_range
{
    typedef bfs::directory_iterator iterator;

    directory_range(bfs::path p) : m_p(p) {}

    iterator begin() { return bfs::directory_iterator(m_p); }

    iterator end() { return bfs::directory_iterator(); }

    bfs::path m_p;
};

One with directory_iterator and same structure with recursive_directory_iterator as iterator recursive_directory_range.

I'm using them in loop like this:

for (const auto &it : directory_range(folder)) {
  if(expression){
    std::cout << "\n :clean: removing file : " << it.path();
    bfs::remove(it.path());
  }
} 

And when I'm using directory_range everything is fine. When I'm switching to recursive_directory_range after first removing I got

filesystem::recursive_directory_iterator directory error: No such file or directory

I have no idea why, because in the docs there is the same statement about these two iterators, that they are not invalidating when doing remove in loops.

Upvotes: 2

Views: 1696

Answers (1)

Steeve
Steeve

Reputation: 1341

From documentation (reference):

If a file is removed from or added to a directory after the construction of a directory_iterator for the directory, it is unspecified whether or not subsequent incrementing of the iterator will ever result in an iterator whose value is the removed or added directory entry.

Also:

The order of the path entries returned by dereferencing successive increments of a directory_iterator is unspecified.

The cause: The most likely scenario that happens here is that you are removing a directory that wasn't iterated yet recursively, and thus you get the error.

Solution: There could be multiple solutions, as an example you could write your own recursive function that uses only a non-recursive directory iterator, which descends to sub-directories first, and deletes the files after all sub-paths have returned.

Upvotes: 1

Related Questions