Generating a relative path in C#

Today I was looking for a way to find a relative path between one absolute directory and another in C#. The .NET libraries themselves don’t seem to have anything that helps with this so I performed the obligatory Google search and came across a handy little function written by Peter Morris which I’ve now incorporated in my library.
I’ve reproduced the code here with some minor changes (aesthetic and personal preference code layout ones), but the work is Peter’s:
public string RelativePath(string absPath, string relTo) {
string[] absDirs = absPath.Split('\\');
string[] relDirs = relTo.Split('\\');
// Get the shortest of the two paths
int len = absDirs.Length < relDirs.Length ? absDirs.Length :
relDirs.Length;
// Use to determine where in the loop we exited
int lastCommonRoot = -1;
int index;
// Find common root
for (index = 0; index < len; index++) {
if (absDirs[index] == relDirs[index]) lastCommonRoot = index;
else break;
}
// If we didn't find a common prefix then throw
if (lastCommonRoot == -1) {
throw new ArgumentException("Paths do not have a common base");
}
// Build up the relative path
StringBuilder relativePath = new StringBuilder();
// Add on the ..
for (index = lastCommonRoot + 1; index < absDirs.Length; index++) {
if (absDirs[index].Length > 0) relativePath.Append("..\\");
}
// Add on the folders
for (index = lastCommonRoot + 1; index < relDirs.Length - 1; index++) {
relativePath.Append(relDirs[index] + "\\");
}
relativePath.Append(relDirs[relDirs.Length - 1]);
return relativePath.ToString();
}
Update
As you can see from a comment below, which was also added to Peter’s site, this does not already exist in the framework in the form of Path.Combine(pathToRelate, absolutePath)
Here’s an example.
If:
pathToRelate = "C:\Inetpub\wwwroot\Project1\Master\Dev\SubDir1";
absolutePath = "C:\Inetpub\wwwroot\Project1\Master\Dev\SubDir2\SubDirIWant";
then using Path.Combine(pathToRelate, absolutePath) returns: C:\Inetpub\wwwroot\Project1\Master\Dev\ which is not the same as what RelativePath(string absPath, string relTo) returns which is ../SubDir2/SubDirIWant/.
6 Responses
did you miss the comments at peters’s site?
string relativePath = Path.Combine(pathToRelate, absolutePath)
(already in the framework)
Hi Caspar, no I didn’t miss the comments on Peter’s site and Path.Combine does not return the same result.
e.g.
Using
Path.Combine()returns:C:\Inetpub\wwwroot\Project1\Master\Dev\which is not what I want. I want the path as it is relative to the absolutePath. Running this through Peter’s function returns:../SubDir2/SubDirIWant/which is what I want.I will amend the post to point this out.
Hi, I found some typo in this code:
)?
can you fix it (for future users
absePath => absPath
relaDirs => relDirs
length => len
Ah, thanks for pointing them out cieszak, fixed as requested!
exactly what i was looking for!
thanks for that, ian!
marco
You’re welcome Marco, glad to be of assistance!