Ahmed A
Ahmed A

Reputation: 3662

recursive_directory_iterator throws exception

I am using the boost iterator "recursive_directory_iterator" to recursively scan through a directory. However, when the iterator runs into a directory for which my application does not have access, exception of type "boost::filesystem3::filesystem_error" is thrown, which halts the iterator and the program aborts. Is there anyway I can instruct the iterator to skip over such directories.

I tried the code suggested at Traversing a directory with boost::filesystem without throwing exceptions However, it did nor work for me. I am using boost version 1.49.

My code after following the suggestion (the best I could come up with), looks as follows:

void scand()
{
    boost::system::error_code ec, no_err;

    // Read dir contents recurs
    for (recursive_directory_iterator end, _path("/tmp", ec);
         _path != end; _path.increment(ec)) {

        if (ec != no_err) {
            _path.pop();
            continue;
        }
        cout << _path->path() << endl;
    }
}

Thank you, Ahmed.

Upvotes: 8

Views: 6988

Answers (3)

Gabriel
Gabriel

Reputation: 3107

To build on andreas' answer. If you have neither std::experimental v2 nor boost, try this. It'll skip over problematic folders.

    namespace fs = std::experimental::filesystem;

    for(std::deque<fs::path> directories{{str_to<std::string>(path)}} ; ! directories.empty() ; directories.pop_front())
        try {
            for(fs::directory_iterator dit(directories.front()) ; dit != fs::directory_iterator() ; ++dit)
                if (fs::is_directory(dit->path()))
                    directories.push_back(dit->path());
                else if (fs::is_regular_file(dit->path()))
                    Handle(dit->path().string());
        }
        catch(...)
        {}

Upvotes: 0

Andreas Magnusson
Andreas Magnusson

Reputation: 7434

This is a known bug in boost::filesystem (V3): https://svn.boost.org/trac/boost/ticket/4494. Depending on your needs you could use V2 of the library instead (it may even come with your compiler in the form of std::tr2::filesystem). Another option is to implement the recursive part yourself.

boost::system::error_code ec;
std::deque<boost::filesystem::path> directories {initialDir};
while(!directories.empty())
{
  boost::filesystem::directory_iterator dit(directories.front(), ec);
  directories.pop_front();
  while(dit != boost::filesystem::directory_iterator())
  {
    if(boost::filesystem::is_directory(dit->path(), ec))
    {
      directories.push_back(dit->path());
    }
    HandleFile(dit->path()); // <-- do something with the file
    ++dit;
  }
}

The above code is just to give a general idea, error checking among other things are missing.

Upvotes: 8

fatihk
fatihk

Reputation: 7929

You can use try-catch blocks and if you catch boost::filesystem3::filesystem_error then you can skip the current iteration:

void scand()
{
   boost::system::error_code ec, no_err;

   // Read dir contents recurs
   recursive_directory_iterator end;
   _path("/tmp", ec);
   while (_path != end) {
      try
      {
        if (ec != no_err) {
         _path.pop();
          continue;
        }
       cout << _path->path() << endl;
    }
    catch(boost::filesystem3::filesystem_error e)
    {

    }
    _path++;
   }
}

Upvotes: 0

Related Questions