Sign in to follow this  
Followers 0
Valik

Au3 Version Of _splitpath

10 posts in this topic

#1 ·  Posted (edited)

Here's a version of _SplitPath in AU3 which seems to emulate the C library function _splitpath well. For those unfamiliar, it takes a path argument and splits it into drive, path, filename and file extension (Including .) components.

There's no return value and no errors. Any missing parts are set to a null string.

EDIT: This version of the code was old.  The newer version is posted somewhere below.

An example of usage and output would be:

Global $path
Global $drive
Global $dir
Global $file
Global $ext
$path = "C:\Program Files\test\moo.cow"
_SplitPath($path, $drive, $dir, $file, $ext)

MsgBox(4096, "_SplitPath", "Path= " & $path & @CRLF & _
    "Drive= " & $drive & @CRLF & _
    "Dir= " & $dir & @CRLF & _
    "File= " & $file & @CRLF & _
    "Ext= " & $ext)

The above should produce the output:

Path= C:\Program Files\test\moo.cow

Drive= C:

Dir= \Program Files\test\

File= moo

Ext= .cow

Edited by Valik

Share this post


Link to post
Share on other sites



Nice :whistle:

Perhaps you could add UNC-style support, e.g. "$path = "\\127.0.0.1\SharedDocs\foo.txt"

might produce something like:

Drive= \\127.0.0.1

Dir= \SharedDocs\

File= foo

Ext= .txt

However, your script works fine as is.


Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!

Share this post


Link to post
Share on other sites

I thought about UNC paths, but I don't know if _splitpath supports them or not and I was attempting to emulate it's functionality. I'll take a look at it later, though and see if I want to add that or not (Should be easy to do, I just want to make sure there's no possible way to confuse it).

However, your script works fine as is.

Shooo. When I saw you, the best obscure bug detecter on the planet, had replied, I thought I'd done something wrong and had a bug. Good to know that you haven't found one... :whistle:

...Yet B)

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

EDIT I changed this post because I changed my mind on what I'm going to do.

I'll modifying _SplitPath to work with UNC paths. I'm also going to write _MakePath and _FullPath which will go along with the C library versions, except I'll make sure they support UNC paths, too. When I finish, I'll post the code here and send it to Jon for inclusion in the standard library thingy.

Edited by Valik

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Here's a new version of _SplitPath which has the following changes:

New: Accepts UNC server names as the drive.

New: Returns an array with the elements in it (See code comment for details)

Fixed: Uses local variables during execution as opposed to the output variables (This was changed in order to prevent a possible bug where the same variable was passed multiple times, for example, $null could be passed for arguments the user didn't want/need).

Watch wordwrap...

; _SplitPath()
; $szPath - IN - The path to be split (Can contain a UNC server or drive letter)
; $szDrive - OUT - String to hold the drive
; $szDir - OUT - String to hold the directory
; $szFName - OUT - String to hold the file name
; $szExt - OUT - String to hold the file extension
; Return - Array with 5 elements where 0 = original path, 1 = drive, 2 = directory, 3 = filename, 4 = extension
; Errors - None.  An empty string denotes a missing component.
Func _SplitPath($szPath, ByRef $szDrive, ByRef $szDir, ByRef $szFName, ByRef $szExt)
  ; Set local strings to null (We use local strings in case one of the arguments is the same variable)
    $drive = ""
    $dir = ""
    $fname = ""
    $ext = ""
    
  ; Create an array which will be filled and returned later
    Dim $array[5]
    $array[0] = $szPath; $szPath can get destroyed, so it needs set now
    
  ; Get drive letter if present (Can be a UNC server)
    If StringMid($szPath, 2, 1) = ":" Then 
        $drive = StringLeft($szPath, 2)
        $szPath = StringTrimLeft($szPath, 2)
    ElseIf StringLeft($szPath, 2) = "\\" Then
        $szPath = StringTrimLeft($szPath, 2)  ; Trim the \\
        $pos = StringInStr($szPath, "\")
        If $pos = 0 Then $pos = StringInStr($szPath, "/")
        If $pos = 0 Then
            $drive = "\\" & $szPath; Prepend the \\ we stripped earlier
            $szPath = ""  ; Set to null because the whole path was just the UNC server name
        Else
            $drive = "\\" & StringLeft($szPath, $pos - 1)  ; Prepend the \\ we stripped earlier
            $szPath = StringTrimLeft($szPath, $pos - 1)
        EndIf
    EndIf
    
  ; Set the directory and file name if present
    For $i = StringLen($szPath) To 0 Step -1
        If StringMid($szPath, $i, 1) = "\" OR StringMid($szPath, $i, 1) = "/" Then
            $dir = StringLeft($szPath, $i)
            $fname = StringRight($szPath, StringLen($szPath) - $i)
            ExitLoop
        EndIf
    Next
    
  ; If $szDir wasn't set, then the whole path must just be a file, so set the filename
    If StringLen($dir) = 0 Then $fname = $szPath
    
  ; Check the filename for an extension and set it
    For $i = StringLen($fname) To 0 Step -1
        If StringMid($fname, $i, 1) = "." Then
            $ext = StringRight($fname, StringLen($fname) - ($i -1))
            $fname = StringLeft($fname, $i - 1)
            ExitLoop
        EndIf
    Next
    
  ; Set the strings and array to what we found
    $szDrive = $drive
    $szDir = $dir
    $szFName = $fname
    $szExt = $ext
    $array[1] = $drive
    $array[2] = $dir
    $array[3] = $fname
    $array[4] = $ext
    Return $array
EndFunc; _SplitPath()
Edited by Valik

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

(This was changed in order to prevent a possible bug where the same variable was passed multiple times, for example, $null could be passed for arguments the user didn't want/need).

Darn, missed that one!

Style suggestion: If you are a minimalist, you may want to consider this:

; Set the strings and array to what we found
Return StringSplit($szDrive & "|" & $szDir & "|" & $szFName & "|" & $szExt, "|")

Edit: Well, you'd need to change element 0 to what you want.

Edited by CyberSlug

Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!

Share this post


Link to post
Share on other sites

Darn, missed that one!

May not of even existed, I never tested for it, but it _looked_ like it might cause problems so I thought I'd head it off before it became an issue.

Style suggestion:  If you are a minimalist, you may want to consider this:

; Set the strings and array to what we found
Return StringSplit($szDrive & "|" & $szDir & "|" & $szFName & "|" & $szExt, "|")

Edit:  Well, you'd need to change element 0 to what you want.

Personally, I'm not a fan of using the StringSplit method, I'd rather assign by hand. To be honest, though, I never even thought about it. The only reason I added an array at all is simply because I figured somebody would request it at some point. I just use the variables I pass and even then, I don't always need all of those so I pass them a pseudo-null.

Share this post


Link to post
Share on other sites

Here's _MakePath. Watch wordwrap/see comments

; _MakePath()
; $szFullPath - OUT - The newly created full path
; $szDrive - IN - Drive (Can be UNC).  If it's a drive letter, a : is automatically appended
; $szDir - IN - Directory.  A trailing slash is provided if not found (No preceeding slash is added)
; $szFName - IN - The name of the file
; $szExt - IN - The file extension.  A period is supplied if not found in the extension
; Return - The string for the newly created path (Same as $szFullPath)
; Errors - None.  Missing components are ignored and the path is created without it.
; Notes - This doesn't check the validity of the path created, it could contain characters which
;   are invalid on your filesystem.
Func _MakePath(ByRef $szFullPath, $szDrive, $szDir, $szFName, $szExt)

   ; Format $szDrive, if it's not a UNC server name, then just get the drive letter and add a colon
    If StringLen($szDrive) Then 
        If Not(StringLeft($szDrive, 2) = "\\") Then $szDrive = StringLeft($szDrive, 1) & ":"
    EndIf

   ; Format the directory by adding any necessary slashes
    If StringLen($szDir) Then
        If Not(StringRight($szDir, 1) = "\") And Not (StringRight($szDir, 1) = "/") Then $szDir = $szDir & "\"
    EndIf

   ; Nothing to be done for the filename
    
   ; Add the period to the extension if necessary
    If StringLen($szExt) Then
        If Not(StringLeft($szExt, 1) = ".") Then $szExt = "." & $szExt
    EndIf
    
    $szFullPath = $szDrive & $szDir & $szFName & $szExt
    Return $szFullPath
EndFunc; _MakePath()

Share this post


Link to post
Share on other sites

Here's _FullPath. It would surprise me greatly if this function doesn't have bugs as it's a pain to implement. Here it is for your bug-testing pleasure. As always, beware word-wrap and check the comments for more information. Just an up front warning also, this function requires my versions of _SplitPath and _MakePath which are above.

; _FullPath()
; This function creates a path based on the relative path you provide.  For example, if you specify
; "C:\test\folder\..\file.txt", the output would be "C:\test\file.txt" because of the ..\.
; $szABSPath - OUT - The newly created absolute path
; $szRelPath - IN - The relative path
; Return - The newly created absolute path is returned
; Errors - None, if no relative path is specified, the current working directory will be returned
; Notes - This function requires _SplitPath and _MakePath (Which also means it supports UNC)
Func _FullPath(ByRef $szABSPath, $szRelPath)
    Local $drive
    Local $dir
    Local $file
    Local $ext
    Local $wDrive
    Local $wDir
    Local $NULL
    _SplitPath($szRelPath, $drive, $dir, $file, $ext)
    _SplitPath(@WorkingDir, $wDrive, $wDir, $NULL, $NULL)
    
   ; If no drive specified, then we use the working directory to set our path relative to
    If Not StringLen($drive) Then
        $drive = $wDrive
        $dir = $wDir & $dir
    EndIf
    
   ; If the only thing specified was the drive, then return the working directory for that drive
    If Not StringLen($dir) AND Not StringLen($file) And Not StringLen($ext) Then 
        If $drive = $wDrive Then Return _MakePath($szABSPath, $wDrive, $wDir, "", "")
        Return _MakePath($szABSPath, $drive, "\", "", "")
    EndIf

   ; Look for any .\ and ..\
    While StringInStr($dir, ".\") Or StringInStr($dir, "./")
        $nPos = StringInStr($dir, ".\")
        If $nPos = 0 Then $nPos = StringInStr($dir, "./")
        If $nPos = 0 Then ExitLoop
        If StringMid($dir, $npos - 1, 1) = "." Then; It's ..\
            For $i = ($nPos - 3) To 0 Step -1
                If StringMid($dir, $i, 1) = "\" Or StringMid($dir, $i, 1) = "/" Then ExitLoop
            Next
                If $i > 0 Then
                    $dir = StringLeft($dir, $i) & StringRight($dir, StringLen($dir) - ($npos + 1))
                Else
                    $dir = StringRight($dir, StringLen($dir) - ($npos + 1))
                EndIf
        Else   ; It's .\
            $dir = StringLeft($dir, $npos - 1) & StringRight($dir, StringLen($dir) - $npos - 1)
        EndIf
    If Not StringLen($dir) Then $dir = "\"
    WEnd
    Return _MakePath($szABSPath, $drive, $dir, $file, $ext)
EndFunc; _FullPath()

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