Sign in to follow this  
Followers 0
wraithdu

_PathGetRelative() UDF

8 posts in this topic

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
            ExitLoop
        EndIf
        $i += 1
    WEnd
    $i = 1
    $sRelPath = ""
    For $j = 1 To $asTo[0]
        If $i >= $iDiff Then
            $sRelPath &= "\" & $asTo[$i]
        EndIf
        $i += 1
    Next
    $sRelPath = StringTrimLeft($sRelPath, 1)
    $i = 1
    For $j = 1 To $asFrom[0]
        If $i > $iDiff Then
            $sRelPath = "..\" & $sRelPath
        EndIf
        $i += 1
    Next
    If StringRight($sRelPath, 1) == "\" Then $sRelPath = StringTrimRight($sRelPath, 1); remove trailing \
    Return $sRelPath
EndFunc

Share this post


Link to post
Share on other sites



#4 ·  Posted (edited)

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:\") ?

Thanks!


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
$aRet=DllCall("shlwapi.dll","int","PathRelativePathToW","wstr",0,"wstr",@DesktopDir,"int",0x10,"wstr",@WindowsDir,"int",0x10)
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  
Followers 0