file get part (SplitPath alternative/short-form/long-form/correct case)

Post your working scripts, libraries and tools
User avatar
jeeswg
Posts: 6818
Joined: 19 Dec 2016, 01:58
Location: UK

file get part (SplitPath alternative/short-form/long-form/correct case)

21 Apr 2018, 09:06

This function combines various file path functionality I wanted:
- SplitPath alternative that directly returns one part of the path

Code: Select all

q:: ;get file part / convert file path
vPath := "C:\A\B\C\D\E\NameNoExt.Ext"
vPath := A_AhkPath
vPath := A_ScriptFullPath
vPath := Format("{:U}", vPath)

;vList := "p,n,d,x,nnx,dr,pnx,d0,d1,d2,d3,d4,d5,d6,d7,ps,pl,pf,pc"
vList := "p,n,d,x,nnx,dr,pnx,ps,pl,pf,pc,d-7,d-6,d-5,d-4,d-3,d-2,d-1,d0,d1,d2,d3,d4,d5,d6,d7,p-8,p-7,p-6,p-5,p-4,p-3,p-2,p-1,p0,p1,p2,p3,p4,p5,p6,p7,p8"
vOutput := ""
Loop, Parse, vList, % ","
{
	vPart := A_LoopField
	vOutput .= Trim(vPart "`t" JEE_FileGetPart(vPath, vPart)) "`r`n"
}
Clipboard := vOutput
MsgBox, % vOutput
return

;==================================================

JEE_FileGetPart(vPath, vPart)
{
	local
	static vIsV1 := InStr(1, 1,, 0)
	SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
	if (vPart = "p") || (vPart = "path") ;path
		return vPath
	else if (vPart = "n") || (vPart = "name") ;name
		return vName
	else if (vPart = "d") || (vPart = "dir") ;directory
		return vDir
	else if (vPart = "e") || (vPart = "x") || (vPart = "ext") ;extension
		return vExt
	else if (vPart = "nne") || (vPart = "nnx") || (vPart = "NameNoExt") ;name no extension
		return vNameNoExt
	else if (vPart = "dr") || (vPart = "drive") ;drive
		return vDrive
	else if (vPart = "pne") || (vPart = "pnx") || (vPart = "PathNoExt") ;path no extension
		return vDir "\" vNameNoExt
	else if (vPart ~= "^-?\d+$") ;nth part e.g. -3, 3
	&& !(vPart = 0)
	{
		if (vPart < 0)
		{
			vPart := StrSplit(vPath, "\").Length() + 1 + vPart
			if (vPart < 1)
				return
		}
		return StrSplit(vPath, "\")[vPart+0]
	}
	else if (vPart = "d0") || (vPart = "p0") ;handle invalid options: 'd0'/'p0'
	|| (vPart = "d-0") || (vPart = "p-0") ;handle invalid options: 'd-0'/'p-0'
		return
	else if (vPart ~= "^[Dd]\d+$") ;first n parts of directory e.g. 'd3'
	{
		if (vPos := InStr(vDir "\", "\", 0, 1, SubStr(vPart, 2)))
			return SubStr(vDir, 1, vPos-1)
		else
			return vDir
	}
	else if (vPart ~= "^[Pp]\d+$") ;first n parts of path e.g. 'p3'
	{
		if (vPos := InStr(vPath "\", "\", 0, 1, SubStr(vPart, 2)))
			return SubStr(vPath, 1, vPos-1)
		else
			return vPath
	}
	else if (vPart ~= "^[Dd]-\d+$") ;last n parts of directory e.g. 'd-3'
	{
		if (vPos := InStr(vDir, "\", 0, vIsV1-1, SubStr(vPart, 3)))
			return SubStr(vDir, vPos+1)
		else
			return vDir
	}
	else if (vPart ~= "^[Pp]-\d+$") ;last n parts of path e.g. 'p-3' (note: 'p-1' is equivalent to 'n')
	{
		if (vPos := InStr(vPath, "\", 0, vIsV1-1, SubStr(vPart, 3)))
			return SubStr(vPath, vPos+1)
		else
			return vPath
	}
	else if (vPart = "ps") ;path (short)
	{
		vSize := DllCall("kernel32\GetShortPathName", Str,"\\?\" vPath, Ptr,0, UInt,0, UInt)
		VarSetCapacity(vPath2, vSize*2, 0)
		if DllCall("kernel32\GetShortPathName", Str,"\\?\" vPath, Str,vPath2, UInt,vSize, UInt)
			return (SubStr(vPath2, 1, 4) = "\\?\") ? SubStr(vPath2, 5) : vPath2
	}
	else if (vPart = "pl") ;path (long)
	{
		vSize := DllCall("kernel32\GetLongPathName", Str,"\\?\" vPath, Ptr,0, UInt,0, UInt)
		VarSetCapacity(vPath2, vSize*2, 0)
		if DllCall("kernel32\GetLongPathName", Str,"\\?\" vPath, Str,vPath2, UInt,vSize, UInt)
			return (SubStr(vPath2, 1, 4) = "\\?\") ? SubStr(vPath2, 5) : vPath2
	}
	else if (vPart = "pf") ;path (full)
	{
		vSize := DllCall("kernel32\GetFullPathName", Str,"\\?\" vPath, UInt,0, Ptr,0, PtrP,0, UInt)
		VarSetCapacity(vPath2, vSize*2, 0)
		if DllCall("kernel32\GetFullPathName", Str,"\\?\" vPath, UInt,vSize, Str,vPath2, PtrP,0, UInt)
			return (SubStr(vPath2, 1, 4) = "\\?\") ? SubStr(vPath2, 5) : vPath2
	}
	else if (vPart = "pc") ;path (correct case)
	{
		Loop, Files, % vPath, FD
			return A_LoopFileLongPath
	}
}

Code: Select all

q:: ;file set part
vPath := A_AhkPath
;vPath := JEE_FileGetPart(A_AhkPath, "pne")
SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive

vOutput := ""
vOutput .= JEE_FileSetPart(vPath, "p", "C:\DIR\FILE.TXT") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "n", "FILE.TXT") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "d", "C:\DIR") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "d", vDir "\SUBDIR") "`r`n" ;add subdir
vOutput .= JEE_FileSetPart(vPath, "e", "EXT") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "nne", "FILE") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "dr", "ZZZ:") "`r`n"
vOutput .= JEE_FileSetPart(vPath, "pne", "C:\DIR\FILE") "`r`n"
vOutput .= JEE_FileSetPart(vPath, 1, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, 2, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, 3, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, StrSplit(vPath, "\").Length(), "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, StrSplit(vPath, "\").Length()+1, "PART") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, -1, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, -2, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, -3, "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, -StrSplit(vPath, "\").Length(), "PART") "`r`n"
vOutput .= JEE_FileSetPart(vPath, -StrSplit(vPath, "\").Length()-1, "PART") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "d5", "X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "d6", "X\X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "d7", "X\X\X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "p6", "X\X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "p7", "X\X\X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "p8", "X\X\X\X\X\X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "d-1", "X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "d-2", "X\X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "p-1", "X") "`r`n" ;error
vOutput .= JEE_FileSetPart(vPath, "p-2", "X\X") "`r`n" ;error
Clipboard := vOutput
MsgBox, % vOutput
return

;==================================================

JEE_FileSetPart(vPath, vPart, vText)
{
	local
	static vIsV1 := InStr(1, 1,, 0)
	SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
	if (vPart = "p") || (vPart = "path") ;path
		return vText
	else if (vPart = "n") || (vPart = "name") ;name
		return vDir "\" vText
	else if (vPart = "d") || (vPart = "dir") ;directory
		return vText "\" vName
	else if (vPart = "e") || (vPart = "x") || (vPart = "ext") ;extension
	{
		if InStr(vPath, ".")
			return vDir "\" vNameNoExt "." vText
		else
			return vPath "." vText
	}
	else if (vPart = "nne") || (vPart = "nnx") || (vPart = "NameNoExt") ;name no extension
	{
		if InStr(vPath, ".")
			return vDir "\" vText "." vExt
		else
			return vDir "\" vText
	}
	else if (vPart = "dr") || (vPart = "drive") ;drive
		return vText SubStr(vPath, StrLen(vDrive) + 1)
	else if (vPart = "pne") || (vPart = "pnx") || (vPart = "PathNoExt") ;path no extension
	{
		if InStr(vPath, ".")
			return vText "." vExt
		else
			return vText
	}
	else if (vPart = "d0") || (vPart = "p0") ;handle invalid options: 'd0'/'p0'
	|| (vPart = "d-0") || (vPart = "p-0") ;handle invalid options: 'd-0'/'p-0'
		return
	else if (vPart ~= "^-?\d+$") ;nth part e.g. -3, 3
	&& !(vPart = 0) ;nth part
	{
		if (vPart < 0)
		{
			vPart := StrSplit(vPath, "\").Length() + 1 + vPart
			if (vPart < 1)
				return
		}
		if (vPart = 1)
			vPos1 := 0
		else if !(vPos1 := InStr(vPath "\", "\",,, vPart-1))
			return
		if !(vPos2 := InStr(vPath "\", "\",, vPos1+1))
			return
		return SubStr(vPath, 1, vPos1) vText SubStr(vPath, vPos2)
	}
	else if (vPart ~= "^[Dd]\d+$") ;first n parts of directory e.g. 'd3'
	{
		if (vPos := InStr(vDir "\", "\", 0, 1, SubStr(vPart, 2)))
			return vText SubStr(vPath, vPos)
		else
			return
	}
	else if (vPart ~= "^[Pp]\d+$") ;first n parts of path e.g. 'p3'
	{
		if (vPos := InStr(vPath "\", "\", 0, 1, SubStr(vPart, 2)))
			return vText SubStr(vPath, vPos)
		else
			return
	}
	else if (vPart ~= "^[Dd]-\d+$") ;last n parts of directory e.g. 'd-3'
	{
		if (vPos := InStr(vDir, "\", 0, vIsV1-1, SubStr(vPart, 3)))
			return SubStr(vPath, 1, vPos) vText "\" vName
		else
			return
	}
	else if (vPart ~= "^[Pp]-\d+$") ;last n parts of path e.g. 'p-3' (note: 'p-1' is equivalent to 'n')
	{
		if (vPos := InStr(vPath, "\", 0, vIsV1-1, SubStr(vPart, 3)))
			return SubStr(vPath, 1, vPos) vText
		else
			return
	}
}
[EDIT:] Added p3/d-3/p-3 etc functionality (i.e. first/last n parts of path/dir).
[EDIT:] Added more comments.
[EDIT:] Fixed GetFullPathName DllCall line, added "\\?\".
[EDIT:] Added more comments.
[EDIT:] Added Path/Name/Dir/Ext/NameNoExt/Drive/PathNoExt functionality (p/n/d/e or x/dr/pne or pnx etc already existed).
[EDIT:] Added nth part functionality e.g. 3/-3.
[EDIT:] Added JEE_FileSetPart function.
Last edited by jeeswg on 08 Dec 2018, 20:50, edited 6 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Tidy Raney

Re: file get part (SplitPath alternative/short-form/long-form/correct case)

21 Apr 2018, 11:32

god sent! I was just destroying my brain trying to code parts of this

thank you for sharing this
User avatar
jeeswg
Posts: 6818
Joined: 19 Dec 2016, 01:58
Location: UK

Re: file get part (SplitPath alternative/short-form/long-form/correct case)

30 Apr 2018, 15:25

I've added some further functionality to the function:

Code: Select all

q:: ;get last n parts of dir/path
vPath := "C:\A\B\C\D\E\NameNoExt.Ext"
MsgBox, % JEE_FileGetPart(vPath, "d-2") ;D\E
MsgBox, % JEE_FileGetPart(vPath, "d-1") ;E
MsgBox, % JEE_FileGetPart(vPath, "p-2") ;E\NameNoExt.Ext
MsgBox, % JEE_FileGetPart(vPath, "p-1") ;NameNoExt.Ext ;note: 'p-1' is equivalent to 'n'
return
@Tidy Raney: That's great, glad it was useful for you.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6818
Joined: 19 Dec 2016, 01:58
Location: UK

Re: file get part (SplitPath alternative/short-form/long-form/correct case)

08 Dec 2018, 21:03

- I've added a file set part counterpart.
- I've done a fair amount of testing but these functions can be fiddly, so do notify of any issues. And besides I *always* MsgBox the first few before/after paths before doing any batch renaming/moving etc.
- I was recreating some C:\dir\name to C:\dir\SUBDIR\name code, for the umpteenth time, and decided I wanted a handy way to add in a subdir. E.g.

Code: Select all

q:: ;add subdir to path
SplitPath, A_AhkPath,, vDir
MsgBox, % JEE_FileSetPart(A_AhkPath, "d", vDir "\SUBDIR")
return
- I initially wrote a one-off function for it. I don't remember the last time this happened but the next day I woke up with a fully-formed idea for a function, a general set parts function.
- In the past also I've rewritten code many times for: C:\dir\name to C:\NEWDIR\name, and C:\DIR1\subdir\name compare with C:\DIR2\subdir\name, and perhaps other similar situations.
- I try to avoid functions that are too esoteric in favour of more general functions, e.g. I'm working on an AHK general library.
- Another bit of annoying fiddly but common code, I recently added a VarSwap function to my general library.
- @ozzii: Thanks.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Scripts and Functions”

Who is online

Users browsing this forum: robodesign, tmplinshi and 47 guests