Tuesday, April 18, 2006

MSH Convert an Absolute Directory to a Relative Directory

Still working on the conversion.  Now I am working up a script to create solution files that will be consumed by Team Build.  Solution files however require relative references to the projects.  Come to find out there is no functionality built into .NET to do this conversion.  Since I didn't want to pick up any dependencies in my MSH script I created the function in MSH with inspiration from Paul Welter:

 

# function that takes an absolute path and turns it into a relative path
function relativePath([string]$absolutePath, [string]$relativeTo)
{
    # Add some error checking
    
    # split up the paths
    $absoluteDirectories = $absolutePath.Split("\")
    $relativeDirectories = $relativeTo.Split("\")
    
    # Get the shortest of the two paths
    [int] $length = [System.Math]::Min($absoluteDirectories.length, $relativeDirectories.length)
    
    # Use to determine where in the loop we exited
    [int] $lastCommonRoot = -1
    
    # Find common root
    for( $i = 0 ; $i -lt $length ; $i++ )
    {
        if($absoluteDirectories[$i] -ne $relativeDirectories[$i])
        {
            break
        }
        
        $lastCommonRoot = $i            
    }
    
    
    # If we didn't find a common prefix then throw
    if($lastCommonRoot -eq -1)
    {
        throw "The paths $absolutePath and $relativeTo do not have a common prefix path."
    }
    
    # build up the relative path
    [System.Collections.Specialized.StringCollection] $relativePath = new-object System.Collections.Specialized.StringCollection
    
    # add on the ..
    for( $i = $lastCommonRoot + 1 ; $i -lt $absoluteDirectories.length ; $i++ )
    {
        if($absoluteDirectories[$i].length -gt 0)
        {
            $relativePath.Add("..") > null
        }
    }
    
    # add on the folders
    for( $i = $lastCommonRoot + 1 ; $i -lt $relativeDirectories.length ; $i++ )
    {
        $relativePath.Add($relativeDirectories[$i]) > null
    }
    
    [string[]] $relativeParts = new-object String[]($relativePath.Count)
    $relativePath.CopyTo($relativeParts, 0)
    [string] $newPath = [System.String]::Join("\", $relativeParts)
    
    return $newPath
}

relativePath "C:\dir1\dir2\dir5" "C:\dir1\dir2\dir3\dir4\dir6" 
Tuesday, April 18, 2006 4:26:07 PM (Pacific Standard Time, UTC-08:00)   #      Comments [0]   MSH
 


Administration
Sign In