Jump to content
Sign in to follow this  

_PathGetRelative() UDF

Recommended Posts


Here's a UDF adapted from the authors of C.A.F.E. Mod to create a relative path from a source directory (must be a directory) to a destination file or directory. This was written as a reverse compliment to _PathFull(). The returned path will never have a trailing "\", even if it is a drive root. It has 2 @error states: 1 if the source and destination are the same, and 2 if the root drives are different. In both cases the destination path is returned.

I've submitted this for inclusion in the Standard UDF Library.

; #FUNCTION#;===============================================================================
; Name...........: _PathGetRelative
; Description ...: Returns the relative path to a directory
; Syntax.........: _PathGetRelative($sFrom, $sTo)
; Parameters ....: $sFrom   - Path to the source directory
;                  $sTo     - Path to the destination file or directory
; Return values .: Success - Relative path to the destination.
;                 Failure - Returns the destination and Sets @Error:
;                 |1 - $sFrom equlas $sTo
;                  |2 - Root drives of $sFrom and $sTo are different, a relative path
;                       is impossible.
; Author ........: Erik Pilsits
; Modified.......:
; Remarks .......: The returned path will not have a trailing "\", even if it is a root
;                  drive returned after a failure.
;                  Original function by Yann Perrin <yann.perrin+clef@gmail.com> and
;                  Lahire Biette <tuxmouraille@gmail.com>, authors of C.A.F.E. Mod.
; Related .......:
; Link ..........:
; Example .......: Yes
Func _PathGetRelative($sFrom, $sTo)
    Local $asFrom, $asTo, $iDiff, $sRelPath, $i
    If StringRight($sFrom, 1) <> "\" Then $sFrom &= "\"; add missing trailing \ to $sFrom path
    If StringRight($sTo, 1) <> "\" Then $sTo &= "\"; add trailing \ to $sTo
    If $sFrom = $sTo Then Return SetError(1, 0, StringTrimRight($sTo, 1)); $sFrom equals $sTo
    $asFrom = StringSplit($sFrom, "\")
    $asTo = StringSplit($sTo, "\")
    If $asFrom[1] <> $asTo[1] Then Return SetError(2, 0, StringTrimRight($sTo, 1)); drives are different, rel path not possible
; create rel path
    $i = 2
    $iDiff = 1
    While 1
        If $asFrom[$i] <> $asTo[$i] Then
            $iDiff = $i
        $i += 1
    $i = 1
    $sRelPath = ""
    For $j = 1 To $asTo[0]
        If $i >= $iDiff Then
            $sRelPath &= "\" & $asTo[$i]
        $i += 1
    $sRelPath = StringTrimLeft($sRelPath, 1)
    $i = 1
    For $j = 1 To $asFrom[0]
        If $i > $iDiff Then
            $sRelPath = "..\" & $sRelPath
        $i += 1
    If StringRight($sRelPath, 1) == "\" Then $sRelPath = StringTrimRight($sRelPath, 1); remove trailing \
    Return $sRelPath

Share this post

Link to post
Share on other sites

Nice, I've been wanting such a function! :P

One thing though..

ConsoleWrite(_PathGetRelative(@HomeDrive, @ScriptDir))

Returns "Documents and Settings\[username]\Desktop"

Hmmm... :P

The output of this function has neither leading nor trailing slashes, so the relative path from a drive root starts with the first subdirectory. Try reversing your from / to and see the ouput instead.

In your case, if you did

$path = _PathGetRelative(@HomeDrive, @ScriptDir)

you could have easily and correcly done

$resolvedpath = @HomeDrive & "\" & $path

which is what you're after with this function.

Edited by wraithdu

Share this post

Link to post
Share on other sites

I understand what it does but I am not sure when I would need it, anyone can give a short example?? :P

I use it to store relative paths for portable applications where the drive of an app's directory may change.

Share this post

Link to post
Share on other sites

I have a problem using this function, here I have posted the issue http://www.autoitscript.com/forum/index.php?showtopic=91273

How can I correctly check the two paths before send them to this function? Is there a kind of path not supported by this function (like already relative paths, or paths with only "C:\") ?


SFTPEx, AutoCompleteInput_DateTimeStandard(), _ImageWriteResize()_GUIGraduallyHide(): some AutoIt functions.

Lupo PenSuite: all-in-one and completely free selection of portable programs and games.

DropIt: a personal assistant to automatically manage your files.

ArcThemALL!: application to multi-archive your files and folders.

Share this post

Link to post
Share on other sites

Neat alternative I just stumbled across:

; FILE_ATTRIBUTE_DIRECTORY = 0x10, anything else = file
If Not @error Then ConsoleWrite("Relative path created:"&$aRet[1]&@CRLF)

You'll still need to check for if it's on the same drive before the call, and whether one of the paths contains an actual file (set the parameter to 0 for those with a file in the path)... but all in all, a much quicker way.

MSDN link: PathRelativePathTo

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  


Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.