Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get relative path from two absolute paths

I have two absolute filesystem paths (A and B), and I want to generate a third filesystem path that represents "A relative from B".

Use case:

  • Media player managing a playlist.
  • User adds file to playlist.
  • New file path added to playlist relative to playlist path.
  • In the future, entire music directory (including playlist) moved elsewhere.
  • All paths still valid because they are relative to the playlist.

boost::filesystem appears to have complete to resolve relative ~ relative => absolute, but nothing to do this in reverse (absolute ~ absolute => relative).

I want to do it with Boost paths.

like image 778
Lightness Races in Orbit Avatar asked Apr 24 '11 20:04

Lightness Races in Orbit


People also ask

How do you convert an absolute path to a relative path?

The absolutePath function works by beginning at the starting folder and moving up one level for each "../" in the relative path. Then it concatenates the changed starting folder with the relative path to produce the equivalent absolute path.

Can an absolute path be a relative path?

In simple words, an absolute path refers to the same location in a file system relative to the root directory, whereas a relative path points to a specific location in a file system relative to the current directory you are working on.

How do you find the relative path of an absolute path in Python?

path. relpath(path) makes a absolute path to relative path. And if the path provided is itself a relative path then the function returns the same path.


1 Answers

With C++17 and its std::filesystem::relative, which evolved from boost, this is a no-brainer:

#include <filesystem> #include <iostream> namespace fs = std::filesystem; int main() {     const fs::path base("/is/the/speed/of/light/absolute");     const fs::path p("/is/the/speed/of/light/absolute/or/is/it/relative/to/the/observer");     const fs::path p2("/little/light/races/in/orbit/of/a/rogue/planet");     std::cout << "Base is base: " << fs::relative(p, base).generic_string() << '\n'               << "Base is deeper: " << fs::relative(base, p).generic_string() << '\n'               << "Base is orthogonal: " << fs::relative(p2, base).generic_string();     // Omitting exception handling/error code usage for simplicity. } 

Output (second parameter is base)

Base is base: or/is/it/relative/to/the/observer Base is deeper: ../../../../../../.. Base is orthogonal: ../../../../../../little/light/races/in/orbit/of/a/rogue/planet 

It uses std::filesystem::path::lexically_relative for comparison. The difference to the pure lexical function is, that std::filesystem::relative resolves symlinks and normalizes both paths using std::filesystem::weakly_canonical (which was introduced for relative) before comparison.

like image 76
Roi Danton Avatar answered Sep 20 '22 19:09

Roi Danton