Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is boost::filesystem::directory_iterator invalidated by deletion?

I am iterating through a directory, and when an item matches some criteria, I delete it. Can I do it safely from within the loop, or to I have to save paths in an array and delete then later?

I did not find a relevant information in boost::filesystem docs.

like image 389
eudoxos Avatar asked Nov 22 '12 13:11

eudoxos


2 Answers

Quoting the first part of a note attached to the docs of boost::filesystem::directory_iterator (emphasis is my own):

Programs performing directory iteration may wish to test if the path obtained by dereferencing a directory iterator actually exists. It could be a symbolic link to a non-existent file. Programs recursively walking directory trees for purposes of removing and renaming entries may wish to avoid following symbolic links.

I becomes clear that iterating a directory for the purpose of removing files is an officially supported use case and therefore will not invalidate the iterator. Also, quoting the second part of that note:

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. See ISO/IEC 9945 readdir_r().

This is a very specific statement about whether or not a removed file will appear while iterating over a directory. Again, I understand that the iteration process itself remains valid in any case.

Note that ISO/IEC 9945 has similar wording.

like image 146
jlh Avatar answered Sep 22 '22 03:09

jlh


On Windows it's true but I've found an Ubuntu on which the iterator gets invalidated after the remove so the next access throws an exception.

So I ended up using something like this:

    recursive_directory_iterator end;
    for (recursive_directory_iterator itr(folderPath); itr != end; )
    {
        path filePath = *itr++;
        if (is_regular_file(filePath) && filePath.string().find(filter) != std::string::npos)
        {
            if (remove(filePath))
            {
                removedFilesCounter++;
            }
        }
    }
like image 22
kenny mccormick Avatar answered Sep 23 '22 03:09

kenny mccormick