Maybe I’m wrong and there is a faster way. I will only be grateful if someone shows a faster way to get a name without an extension for an individual file .
set posixPath to POSIX path of (choose file)
----------------------------------------------------------------------------------------------------
set TID to text item delimiters
set text item delimiters to {"/"}
set baseName to last text item of posixPath
set text item delimiters to {"."}
try
set nameWithoutExtension to text item -2 of baseName
on error
set nameWithoutExtension to baseName
end try
set text item delimiters to TID
nameWithoutExtension
Without set posixPath to POSIX path of (choose file) code line on my machine all process takes about 1.3 microseconds
set aFile to (choose file)
set {name:Nm, name extension:Ex} to (info for aFile) -- info for is deprecated for ages but is still working
set baseName to text 1 thru ((get offset of "." & Ex in Nm) - 1) of Nm
set posixPath to POSIX path of (choose file)
set baseName to (current application's NSURL's fileURLWithPath:posixPath)'s URLByDeletingPathExtension()'s lastPathComponent() as text
set posixPath to POSIX path of (choose file)
set TID to text item delimiters
set text item delimiters to {"/"}
set baseName to last text item of posixPath
set text item delimiters to {"."}
try
set nameWithoutExtension to (text items 1 thru -2 of baseName) as string
on error
set nameWithoutExtension to baseName
end try
set text item delimiters to TID
nameWithoutExtension
set posixPath to POSIX path of (choose file)
set TID to text item delimiters
set text item delimiters to {"/"}
if (posixPath ends with "/") then
set baseName to text item -2 of posixPath
else
set baseName to last text item of posixPath
end if
if (baseName contains ".") then
set text item delimiters to {"."}
set nameWithoutExtension to text 1 thru text item -2 of baseName
else
set nameWithoutExtension to baseName
end if
set text item delimiters to TID
nameWithoutExtension
Thanks, Nigel. Your script takes about 1.85 microseconds, so your solution for “.” problem is preferable from mine. I can’t still understand why it is faster. It is using text instead of as string, I think. Or, removing the try block ?.
Oh, I understand. No need try block, because if not dots in base name, base name has not extension!
And, you added if (posixPath ends with “/”) then for bundles and packages! Yes, your script goes as the best to my Scripts library.
I didn’t actually time it. The main aim was make your own script slightly more reliable. But text 1 thru text item -2 of basename is slightly more efficient than (text items 1 thru -2 of baseName) as string because it extracts the substring directly instead of creating and coercing an intermediate list. In the case of tryvs.if, it seems to be a matter of overall balance. When there is an extension, the if statement adds a test into the process, but this has apparently been offset by using text 1 thru text item -2… instead of (text items 1 thru -2…. When there isn’t an extension, the time taken to do the test and nothing else is likely to be very much less than the time taken to reset the TIDs, attempt the text extraction, and recover from the error.
Stefan’s suggestion above can be done entirely with NSString methods. It might be interesting to see how these compare with the NSURL ones:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set posixPath to POSIX path of (choose file)
set baseName to (current application's NSString's stringWithString:posixPath)'s stringByDeletingPathExtension()'s lastPathComponent() as text
-- Or (with a shorter intermediate string):
set baseName to (current application's NSString's stringWithString:posixPath)'s lastPathComponent()'s stringByDeletingPathExtension() as text
OK, I tested again. The first code line takes about 27 microseconds, the second - about 25 microseconds. It seems, 3 ASObjC methods uses the same algorithm :).
Here’s a slight modification of Nigel’s script that retains the period character in the nameWithoutExtension return value for base names that end with a period character, in which case the period character does not serve as a file extension delimiter. The only change is the addition of the phrase and (baseName does not end with “.”)
set posixPath to POSIX path of (choose file)
set TID to text item delimiters
set text item delimiters to {"/"}
if (posixPath ends with "/") then
set baseName to text item -2 of posixPath
else
set baseName to last text item of posixPath
end if
if (baseName contains ".") and (baseName does not end with ".") then
set text item delimiters to {"."}
set nameWithoutExtension to text 1 thru text item -2 of baseName
else
set nameWithoutExtension to baseName
end if
set text item delimiters to TID
nameWithoutExtension
There may not be much point to your modification. Both versions work in all cases. Yours saves having to set and use the TIDs when the name ends with “.”, but adds an extra check which is carried out with every name containing that character.
When I apply the code to the sample POSIX path “/qwer/asdf/zxcv.”, the original version returns “zxcv” for nameWithoutExtension, whereas the proposed modified version returns “zxcv.”, which I believe is the correct name without extension. Am I missing something?
Maybe I am. I’d consider a trailing “.” to be either the extension or the separator between the rest of the name and an implied “” extension. However, applying NSString or NSURL methods to the task returns your result:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
set aPath to current application's class "NSString"'s stringWithString:("/qwer/asdf/zxcv.")
set nameWithoutExtension to (aPath's lastPathComponent()'s stringByDeletingPathExtension()) as text
-- "zxcv."
But then again, they return “” for the extension itself. In all other cases, both the extension and the dot are removed, so it’s inconsistent.
I understand your point. One case where the period would be part of the name rather than the extension would be the hidden files “.” and “…”, no? But outside of that peculiar case, I suppose that because it’s not customary to name files with a trailing period, there is some ambiguity in its interpretation.
This file has no extension and the 19 at the end of the file name is the current year.
Every script in this thread (except for two that wouldn’t work for me) returned a file name without extension as:
Test File 12.12
Even a Finder window shows the file name with extension hidden as:
Test File 12.12
I ran the following script on the test file:
tell application "Finder"
set thefile to selection as alias
set fileName to name of thefile
set fileExtension to name extension of thefile
if fileExtension > "" then
set fileNameWithoutExtension to text 1 thru -((count fileExtension) + 2) of fileName
else
set fileNameWithoutExtension to fileName
end if
end tell
fileNameWithoutExtension
This script recognizes that 19 is part of the file name and not an extension and correctly returns fileNameWithoutExtension as:
Test File 12.12.19
How does this script identify 19 as part of the file name and not an extension–or is something else going on?
Others may correct me if I’m wrong, but I don’t think it’s possible to name a file with a period (i.e., character id 46) following by non-period characters. The portion of the name beginning with the final period will always be interpreted as a file extension. In the above case, .19 would always be interpreted as being a file extension. I don’t know of any way to get around this restriction other than perhaps to replace the period characters with middle dot characters (character id 183), hyphens, or something similar in the file name:
Thanks bmose. What you say makes absolute sense to me. In fact, I ran “info for” on my test file and it showed the file extension to be “19”. What confused me was that my script when run on the test file returns “” (i.e. an empty string) for the fileExtension variable. I think I’m making some rookie mistake in my script but I can’t figure it out.