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