Question

How can I determine if file is contained by path with boost filesystem v3.

I saw that there is a lesser or greater operator but this seems to be only lexical. The best way I saw was the following:

  • Take the two absolute paths of the file and the path
  • Remove the last part of the file and see if it equals the path (if it does it's contained)

Is there any better way to do this?

Was it helpful?

Solution

The following function should determine whether a file name lies somewhere within the given directory, either as a direct child or in some subdirectory.

bool path_contains_file(path dir, path file)
{
  // If dir ends with "/" and isn't the root directory, then the final
  // component returned by iterators will include "." and will interfere
  // with the std::equal check below, so we strip it before proceeding.
  if (dir.filename() == ".")
    dir.remove_filename();
  // We're also not interested in the file's name.
  assert(file.has_filename());
  file.remove_filename();

  // If dir has more components than file, then file can't possibly
  // reside in dir.
  auto dir_len = std::distance(dir.begin(), dir.end());
  auto file_len = std::distance(file.begin(), file.end());
  if (dir_len > file_len)
    return false;

  // This stops checking when it reaches dir.end(), so it's OK if file
  // has more directory components afterward. They won't be checked.
  return std::equal(dir.begin(), dir.end(), file.begin());
}

If you just want to check whether the directory is the immediate parent of the file, then use this instead:

bool path_directly_contains_file(path dir, path file)
{
  if (dir.filename() == ".")
    dir.remove_filename();
  assert(file.has_filename());
  file.remove_filename();

  return dir == file;
}

You may also be interested in the discussion about what "the same" means with regard to operator== for paths.

OTHER TIPS

If you just want to lexically check if one path is a prefix of another, without worrying about ., .. or symbolic links, you can use this:

bool path_has_prefix(const path & path, const path & prefix)
{
    auto pair = std::mismatch(path.begin(), path.end(), prefix.begin(), prefix.end());
    return pair.second == prefix.end();
}

Note that the four parameter overload of std::mismatch used here wasn't added until C++14.

Of course, if you want more than a strictly lexical comparison of the paths, you can call lexically_normal() or canonical() on either or both parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top