Hi,
sometimes it is useful, to know the name of a path relative to a given directory. The following code converts an absolute path to a relative path.
Regards, Little John
//edit 2010-09-22: Slightly simplified the code.
Code: Select all
; -- Convert an absolute path to a relative one.
; Tested with PB 4.51 on Windows XP and Ubuntu 10.04
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
#Slash = '\'
#BadSlash = '/'
CompilerDefault
#Slash = '/'
#BadSlash = '\'
CompilerEndSelect
Procedure.i EqualPathLen (s1$, s2$)
; -- return length of identical part of the paths in s1$ and s2$
Protected maxEqual, temp, equal, ret
Protected *p1.Character, *p2.Character
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
s1$ = UCase(s1$)
s2$ = UCase(s2$)
CompilerEndIf
maxEqual = Len(s1$)
temp = Len(s2$)
If maxEqual > temp
maxEqual = temp
EndIf
*p1 = @s1$
*p2 = @s2$
equal = 0
ret = 0
While equal < maxEqual And *p1\c = *p2\c
equal + 1
If *p1\c = #Slash
ret = equal
EndIf
*p1 + SizeOf(character)
*p2 + SizeOf(character)
Wend
ProcedureReturn ret
EndProcedure
Procedure.s RelativePath (baseDir$, absPath$)
; -- convert an absolute path to a relative one
; in : baseDir$: full name of a directory, with trailing (back)slash
; absPath$: full name of a path to a directory or file
; out: absPath$ converted, so that it is relative to baseDir$
Protected equal, s, i, parent$, ret$=""
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
If UCase(Left(baseDir$, 1)) <> UCase(Left(absPath$, 1))
ProcedureReturn absPath$ ; can't build a relative path
EndIf
CompilerEndIf
ReplaceString(baseDir$, Chr(#BadSlash), Chr(#Slash), #PB_String_InPlace)
ReplaceString(absPath$, Chr(#BadSlash), Chr(#Slash), #PB_String_InPlace)
equal = EqualPathLen(baseDir$, absPath$)
s = CountString(Mid(baseDir$, equal+1), Chr(#Slash))
parent$ = ".." + Chr(#Slash)
For i = 1 To s
ret$ + parent$
Next
ProcedureReturn ret$ + Mid(absPath$, equal+1)
EndProcedure
;-- Demo
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
Debug RelativePath("F:\Data\John\", "f:\Data\John\PC")
Debug RelativePath("F:\Data\John\", "f:\Data\John\")
Debug RelativePath("F:\Data\John\", "f:\Data\John")
Debug RelativePath("F:\Data\John\", "f:\Data\Peter\")
Debug RelativePath("F:\Data\John\", "f:\")
Debug RelativePath("F:\", "f:\Data\John\")
Debug RelativePath("F:\Data\John\", "g:\Videos")
CompilerDefault
Debug RelativePath("/media/Corsair/Data/John/", "/media/Corsair/Data/John/PC")
Debug RelativePath("/media/Corsair/Data/John/", "/media/Corsair/Data/John/")
Debug RelativePath("/media/Corsair/Data/John/", "/media/Corsair/Data/John")
Debug RelativePath("/media/Corsair/Data/John/", "/media/Corsair/Data/Peter/")
Debug RelativePath("/media/Corsair/Data/John/", "/media/Corsair/")
Debug RelativePath("/media/Corsair/", "/media/Corsair/Data/John/")
Debug RelativePath("/media/Corsair/Data/John/", "/media/Maxtor/Videos")
CompilerEndSelect