6

So... I have a base path and a new path.New path contains in it base path. I need to see what is different in new path. Like we had /home/ and new path is /home/apple/one and I need to get from it apple/one. note - when I would create some path from (homePath/diffPath) I need to get that /home/apple/one again. How to do such thing with Boost FileSystem?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Rella
  • 65,003
  • 109
  • 363
  • 636

3 Answers3

9

Using stem() and parent_path() and walk backwards from the new path until we get back to base path, this works, but I am not sure if it is very safe. Be cautious, as the path "/home" and "/home/" are treated as different paths. The below only works if base path is /home (without trailing slash) and new path is guaranteed to be below base path in the directory tree.

#include <iostream>
#include <boost/filesystem.hpp>
int main(void)
{
  namespace fs = boost::filesystem;

  fs::path basepath("/home");
  fs::path newpath("/home/apple/one");
  fs::path diffpath;

  fs::path tmppath = newpath;
  while(tmppath != basepath) {
    diffpath = tmppath.stem() / diffpath;
    tmppath = tmppath.parent_path();
  }

  std::cout << "basepath: " << basepath << std::endl;
  std::cout << "newpath: " << newpath << std::endl;
  std::cout << "diffpath: " << diffpath << std::endl;
  std::cout << "basepath/diffpath: " << basepath/diffpath << std::endl;

  return 0;
}
Oskar N.
  • 8,427
  • 2
  • 23
  • 21
  • 1
    Instead of using `while(tmppath != basepath)` using `while(!fs::equivalent(tmppath,basepath))` is more robust. – Hardik Jain Dec 10 '18 at 13:46
3

Assuming you have:

namespace fs = std::filesystem; // or boost::filesystem

fs::path base = "/home/usera"
fs::path full = "/home/usera/documents/doc"

If you want to extract documents/doc, you can do that with lexically_relative:

fs::path diff = full.lexically_relative(base);
assert( diff == fs::path("documents/doc") );

This works for base = "/home/usera" or base = "home/usera/". If full does not contain base, this may give you a pretty long path with lots of .. instead of getting an error.

std::filesystem::path::lexically_relative requires C++17

Stewart
  • 4,356
  • 2
  • 27
  • 59
0

Other solution, if you know that newpath really belongs to basepath, could be:

auto nit = newpath.begin();

for (auto bit = basepath.begin(); bit != basepath.end(); ++bit, ++nit)
    ;

fs::path = path(nit, newpath.end());
ABu
  • 10,423
  • 6
  • 52
  • 103