Page 1 of 1

PathX() : Split & modify a filepath easily

Posted: 22 Aug 2023, 03:44
by SKAN
PathX() is an alternative solution for SplitPath(). It breaks down a fullpath to individual parts and returns them as an object. Note that the results from PathX() will be different from SplitPath(). The common reason a filepath is split is to concatenate them back again to form a different filepath. PathX() can do this in one go. Custom key values can be provided as variadic parameters to substitute individual parts of the returned array.
 
PathX() is powered by two API functions
 
PathX(Path, X*)
PathX() splits a filepath and returns filepath parts as an object with following properties:

  • 1) Drive
  • 2) Dir
  • 3) Fname (Filename without extension)
  • 4) Ext
  • 5) Folder (Concatenation of 1 & 2)
  • 6) File (Concatenation of 3 & 4)
  • 7) Full (Concatenation of 1,2,3 & 4)
 
 
Try the following example to see the properties returned:

Code: Select all

#Requires AutoHotkey v2.0

Px := PathX(A_AhkPath)
MsgBox( "Drive`t:`t"    Px.Drive   "`n"
      . "Dir`t:`t"      Px.Dir     "`n"
      . "Fname`t:`t"    Px.Fname   "`n"
      . "Ext`t:`t"      Px.Ext     "`n"
      . "Folder`t:`t"   Px.Folder  "`n"
      . "File`t:`t"     Px.File    "`n"
      . "Full`t:`t"     Px.Full
      , "PathX(A_AhkPath)" )
 
Image
 
 
The first 4 properties Drive, Dir, Fname and Ext can be overwritten with custom values:

Code: Select all

MsgBox( PathX(A_ScriptName, "Fname:Hello World").Full, "Change name"         )
MsgBox( PathX(A_ScriptName, "Drive:Z:").Full,          "Change drive"        )
MsgBox( PathX(A_ScriptName, "Dir:\").Full,             "Change path to root" )
MsgBox( PathX(A_ScriptName, "Ext:.txt").Full,          "Change extension"    )
 
PathX() will resolve relative path to fullpath unconditionally:

Code: Select all

MsgBox( PathX("..\" . A_ScriptName).Full,                  "One level up"    )
MsgBox( PathX("Sub_folder\Sub_folder\" A_ScriptName).Full, "Two levels down" )
 
One may pass multiple parameters as well as shorten the key names to two chars:
The following example shows how to substitute Drive and Fname in one go.
Note: Make sure there are no spaces between Key:Value unless it was intended.

Code: Select all

MsgBox( PathX(A_ScriptName, "Dr:X:", "Fn:MyScript").Full, "New path" )
 
Keys Fprefix and Fsuffix can be used to add prefix/suffix to Fname.

Code: Select all

MsgBox( PathX(A_ScriptName, "fp:Copy of ").Full,                     "Prefix Fname"  )
MsgBox( PathX(A_ScriptName, "fs:_001").Full,                         "Suffix Fname"  )
MsgBox( PathX(A_ScriptName, "fp:Backup_", "fs:" . "_" . A_Now).Full, "Prefix/Suffix" ) 
 
Additional file extension can be kind of prefixed indirectly by suffixing Fname.

Code: Select all

MsgBox( PathX(A_AhkPath, "fs:.old").Full, "Prefix extension" )
 
Keys Dprefix and Dsuffix may be used to add prefix/suffix to Dir.

Code: Select all

MsgBox( PathX(A_ScriptName, "Dr:N:", "dp:\Backup", "ds:001\").Full, "Prefix/Suffix Dir")
 
Keys Pprefix and Psuffix may be used to add prefix/suffix to Fullpath.

Code: Select all

MsgBox( PathX(A_ScriptName, "pp:file:///").Full,    "Prefix fullpath" )
MsgBox( PathX(A_ScriptName, "pp:\\?\").Full,        "Prefix fullpath" )
MsgBox( PathX(A_ScriptName, "ps::HiddenData").Full, "Suffix ADS name" )
 
Within Loop Files, A_LoopFileName is available but no built-in var for base file name (file name without extension).
PathX() can be used as follows:

Code: Select all

Loop Files, A_AhkPath "\..\*.exe"
    MsgBox( PathX(A_LoopFileFullPath).FName )
 
While File extension can be forced with Ext key for File save dialog...

Code: Select all

sfile   :=  FileSelect("S2", A_DeskTop "\test", "Select save file",  "Documents (*.*)")
sfile2  :=  sfile ? PathX(sfile, "Ext:.txt").Full : ""
MsgBox( sFile "`n" sFile2 )
... *Ext key will add extension only if not already present:

Code: Select all

sfile  :=  FileSelect("S2", A_DeskTop "\test", "Select save file",  "Documents (*.txt)")
sfile2 :=  sfile ? PathX(sfile, "*Ext:.txt").Full : ""
MsgBox( sFile "`n" sFile2 )

 
The function:
 

Code: Select all

PathX(Path, X*)             ; PathX() v0.67 by SKAN for ah2 on D34U/D68M @ autohotkey.com/r?p=120582
{
    Local  K,V,N,U, Dr,   Di,   Fn,   Ex
        ,  FPath := Dr := Di := Fn := Ex := Format("{:260}", "")

    U := Map(),  U.Default := "",  U.CaseSense := 0

    For  K, V  in  X
         N     :=  StrSplit(V, ":",, 2)  ;  split X into Key and Value
      ,  K     :=  SubStr(N[1], 1, 2)    ;  reduce Key to leading 2 chars
      ,  U[K]  :=  N[2]                  ;  assign Key and Value to Map

    DllCall("Kernel32\GetFullPathNameW", "str",Trim(Path,Chr(34)), "uint",260, "str",FPath, "ptr",0)
    DllCall("Msvcrt\_wsplitpath", "str",FPath, "str",Dr, "str",Di, "str",Fn, "str",Ex)

    Return {  Drive  :  Dr  :=  U["Dr"] ? U["Dr"] : Dr
           ,  Dir    :  Di  :=  U["dp"] ( U["Di"] ? U["Di"] : Di ) U["ds"]
           ,  Fname  :  Fn  :=  U["fp"] ( U["Fn"]!="" ? U["Fn"] : Fn )  U["fs"]
           ,  Ext    :  Ex  :=  U["*E"]!="" ? ( Ex ? Ex : U["*E"] ) : ( U["Ex"]!="" ? U["Ex"] : Ex )
           ,  Folder :  Dr Di
           ,  File   :  Fn Ex
           ,  Full   :  U["pp"] ( Dr Di Fn Ex ) U["ps"] }
}

PathU() : Adds incremental number to filename to make a filepath unique

Posted: 22 Aug 2023, 03:50
by SKAN
PathU(Filename)
Returns a fully qualified path that is unique in entire filesystem.
 
The function: (Along with examples)

Code: Select all

PathU(Filename)              ;  PathU v0.91 by SKAN for ah2 on D35E/D68M @ autohotkey.com/r?p=535235
{
    Local  OutFile := Format("{:260}", "")
    DllCall("Kernel32\GetFullPathNameW", "str",Filename, "uint",260, "str",OutFile, "ptr",0)
    DllCall("Shell32\PathYetAnotherMakeUniqueName", "str",OutFile, "str",OutFile, "ptr",0, "ptr",0)
    Return OutFile
}

#Requires AutoHotkey v2.0
#SingleInstance

MsgBox( PathU(A_ScriptFullPath) )               ; to copy a backup of this script
MsgBox( PathU(A_ScriptName) )                   ; A_WorkingDir is used to resolve fullpath
MsgBox( PathU(A_AhkPath . "\..\License.txt") )  ; relative path is auto-resolved
MsgBox( PathU(A_ScriptDir) )                    ; Works for folder too..Avoid trailing slash!
MsgBox( PathU(A_Temp . "\ahk.tmp") )            ; Simple way to create a temp file

Re: PathX() : Split & modify a filepath easily

Posted: 23 Aug 2023, 02:03
by ozzii
Thank you SKAN.
Always a pleasure to read all of your exemples.

Re: PathX() : Split & modify a filepath easily

Posted: 23 Aug 2023, 04:05
by SKAN
Hi @ozzii :) :thumbup:

Re: PathX() : Split & modify a filepath easily

Posted: 26 Mar 2024, 03:31
by tdalon
Many thanks @SKAN
Perfectly done and you saved me some time.