Given two absolute paths, e.g.
/a/path/to/a
/a/path/to/somewhere/else
How can I get a relative path from one to the other, ../a
?
In a sense, the opposite of what realpath
does.
I answered a similar question here: Resolving a relative path without referencing the current directory on Windows.
There is no standard function for this. There is a function in vi-like-emacs for this purpose. A quick check of apropos relative
shows me few other programs which likely implement this: revpath for example).
It could be done as a string-manipulation (no need to compute working directories):
The "done" in the second step presumes that you want to use a relative path to shorten the result. On the other hand, you might want to use a relative pathname regardless of the length. In that case, just skip the step (the result will be longer, but relative).
Find the longest common path (in this case, /a/path/to
) and delete it from both absolute paths. That would give:
/a
/somewhere/else
Now, replace each path component in the starting path with ../
and prepend the result to the destination path. If you want to go from directory else
to directory a
, that would give you:
../../a
If you want to go the other way, you'd instead have:
../somewhere/else
Build a tree with the first absolute path, then add the second path to that tree, and then walk from one leaf to the other: a step from one node to its parent is translated to a "../" sequence, and a step from a node to one of its children is translated to the name of that children. Notice that there might be more than one solution. For example:
1) /a/path/to/a
And
2) /a/path/to/a/new/one
The obvious path from (1) to (2) is new/one
but ../../../a/path/to/a/new/one
is also valid. When you write the algorithm to do the walking in your tree you have to be aware of this
Using cwalk you can use cwk_path_get_relative, which even works cross-platform:
#include <cwalk.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buffer[FILENAME_MAX];
cwk_path_get_relative("/hello/there/", "/hello/world", buffer, sizeof(buffer));
printf("The relative path is: %s", buffer);
return EXIT_SUCCESS;
}
Output:
The relative path is: ../world
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With