finder - extract filename from posix path

set p to "/Users/myAccount/Desktop/file.txt"
set a to POSIX file p

How would you extract just the “file.txt” from the posix path?

thanks

You may try :

set p to "/Users/myAccount/Desktop/file.txt"
tell application "System Events"
	set pName to name of disk item p
end tell
set a to POSIX file p
tell application "Finder"
	set fName to  name of (a as alias)
end tell
fname = pName

Yvan KOENIG running El Capitan 10.11.3 in French (VALLAURIS, France) lundi 21 mars 2016 19:25:50

Hi,

given

set p to "/Users/myAccount/Desktop/file.txt"

we have

¢ the text item delimiters way

set TID to text item delimiters
set text item delimiters to {"/"}
set n to last text item of p
set text item delimiters to TID

¢ the shell script way

set n to do shell script "basename " & quoted form of p

¢ The System Events way

tell application "System Events" to set n to name of disk item p

¢ The deprecated but still working info for way

set n to name of (info for (POSIX file p as alias))

¢ And last but not least the AppleScriptObjC way

use framework "Foundation"

set url to current application's NSURL's fileURLWithPath:p
set n to url's lastPathComponent() as text

Of course there is also the Finder way, but I’d recommend all other suggestions

thats it thanks for the reply!

And a regex way (to complete Stefan’s list).

Regex using AppleScript Toolbox.osax (you can use grep, sed, awk command line utils, satimage.osax or AppleScriptObjC for example):

first item of (AST find regex "[^/]+$" in string p)

I apologize but the code relying upon TID requires a change because, as is, if p is a path to a folder it returns “”.

set p to "/Users/myAccount/Desktop/aFolder/"
set TID to text item delimiters
set text item delimiters to {"/"}
set n to last text item of p
if n = "" then set n to text item -2 of p
set text item delimiters to TID
n

The problem is the same with the regex scheme which returns missing value if we ask it to treat a path to a folder.

Yvan KOENIG running El Capitan 10.11.4 in French (VALLAURIS, France) mardi 22 mars 2016 11:03:08

Yvan, the topic and the body of the question are clearly about a file not a folder.

A POSIX path to a folder doesn’t have to end with a slash, although it usually does if created with ‘POSIX path of .’. This can be caught by including an optional slash at the end of the regex: “[^/]+/?$”. How you lose the slash if it’s there depends on the facility you’re using:

set p to "/Users/myAccount/Desktop/aFolder/"

-- AppleScript Toolbox:
set n to first item of (AST find regex "([^/]+)/?$" in string p regex group 2) -- Group 1 = entire match, group 2 = first parenthesised group.

-- Satimage OSAX:
set n to (find text "[^/]+(?=/?$)" in p with regexp and string result)

-- sed:
set n to (do shell script "sed -E 's|^.+/([^/]+)/?$|\\1|' <<<" & quoted form of p)

Just thought of this: :slight_smile:

set p to "/Users/myAccount/Desktop/aFolder/"
set TID to text item delimiters
set text item delimiters to {"//", "/"} -- NB. "//" before "/".
set n to text item -2 of (p & "/")
set text item delimiters to TID
n

A more safer way against the plain AppleScript solution, including my own, as POSIX standard describes. Knowing that POSIX Paths in AppleScript in real world situations don’t two trailing slashes for instance or the entire path is only 3 slashes, it should be supported to make it POSIX reliable.


POSIXBaseName("/Users/myAccount/Desktop/aFolder/") -- result: "aFolder"
POSIXBaseName("/Users") --result: "Users"
POSIXBaseName("/") -- result: "/"
POSIXBaseName("///") -- result: "/"
POSIXBaseName("//Users//myAccount//") -- result:"myAccount"

on POSIXBaseName(thePath)
	-- Like the POSIX standard
	-- Accoring to the POSIX standard "//" is implementation defined,
	-- returning "/" or "//" is good either way. "/" is returned
	if thePath = missing value or thePath is "" then return "."
	
	tell AppleScript
		set oldTIDs to text item delimiters
		set text item delimiters to "/"
		set pathComponents to text items of thePath
		set text item delimiters to oldTIDs
	end tell
	
	repeat with i from (count of pathComponents) to 1 by -1
		if item i of pathComponents is not "" then return item i of pathComponents
	end repeat
	
	return "/"
end POSIXBaseName

Using a regex the implementation would look like:


POSIXBaseName("/Users/myAccount/Desktop/aFolder/") -- result: "aFolder"
POSIXBaseName("/Users") --result: "Users"
POSIXBaseName("/") -- result: "/"
POSIXBaseName("///") -- result: "/"
POSIXBaseName("//Users//myAccount//") -- result:"myAccount"

on POSIXBaseName(thePath)
	-- Like the POSIX standard
	-- Accoring to the POSIX standard "//" is implementation defined,
	-- returning "/" or "//" is good either way. "/" is returned
	if thePath = missing value or thePath is "" then return "."
	
	-- regex updated, see Nigel's post below
	set regMatch to AST find regex "([^/]+|^/)/*$" in string thePath regex group 2
	return first item of regMatch
end POSIXBaseName

Using AppleScriptObjC. The pipes around NSURL are required since I have XML Tools installed on my system and NSURL turns into an enumerated value of this OSAX.

use framework "Foundation"
property |NSURL| : class "NSURL"

POSIXBaseName("/Users/myAccount/Desktop/aFolder/") -- result: "aFolder"
POSIXBaseName("/Users") --result: "Users"
POSIXBaseName("/") -- result: "/"
POSIXBaseName("///") -- result: "/"
POSIXBaseName("//Users//myAccount//") -- result:"myAccount"

on POSIXBaseName(thePath)
        -- see StefanK post above
	if thePath is missing value or thePath is "" then return "."
	set theURL to |NSURL|'s fileURLWithPath:thePath
	set basename to theURL's lastPathComponent() as text
	return basename
end POSIXBaseName

"

Yeah. You could add progressively longer delimiters to the front of the list in my multi-delimiter approach, but it would be begin to look less elegant. The method also depends on the delimiters being applied in the order they are in the list, which is a reasonable expectation and what happens at the moment, but I haven’t seen it documented anywhere, so it may not a safe assumption!

An alternative to this would be:

	set regMatch to AST find regex "([^/]+|^/)/*$" in string thePath regex group 2
	return first item of regMatch

The AppleScriptObjC version mentioned in my answer considers all cases reliably.

I was just filling the list of all the possibilities and different implementations. In real world situations you have sometimes paths beginning with double slashes or in the middle of it but rarely having multiple trailing slashes. I think for supporting path concatenation, I see no other reason for supporting it, in theory you can have consecutive slashes everywhere in the paths.

Thanks again Nigel :cool: I’ll update the post

Great, I wasn’t expecting otherwise to be honest. To complete the list I’ll add you handler to it.

You might like to remove the colon in the use framework statement.