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?

Était-ce utile?

La 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.

Autres conseils

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top