Why Doesn't This Code Work?

Hi Shane. I don’t think you meant to include the first line.

Nigel, does it make more sense now? I was referring to separate scripts…

Hi Shane.

text 1 thru -1 of (the reverse of every character of thisName) produces a list. I got the impression your intention was to demonstrate a direct substring extraction.

set thisName to "fred.jpg"
set thisName to text 1 thru -1 of (the reverse of every character of thisName)
--> {"g", "p", "j", ".", "d", "e", "r", "f"}

I looked carefully at the pointed thread and discovered that you misunderstood what I wrote.

It’s not what I pointed to.

on removeExtension(thisName)
	if thisName contains "." then
		set thisName to (the reverse of every character of thisName) as string
		set x to the offset of "." in thisName
		set thisName to (text (x + 1) thru -1 of thisName)
		set thisName to (the reverse of every character of thisName) as string
	end if
	return thisName
end removeExtension


-- what you posted. It behaves flawlessly
-- bad choice of variable name, it's not a name but a path
set thisName to "Macintoh HD:Users:moi:Documents:31.12.43:Image-12.22.09.bmp"
my removeExtension(thisName) --> "Macintoh HD:Users:moi:Documents:31.12.43:Image-12.22.09"

-- what I pointed to. It returns an awful result
-- bad choice of variable name, it's not a name but a path
set thisName to "Macintoh HD:Users:moi:Documents:31.12.43:myFile"
my removeExtension(thisName) --> "Macintoh HD:Users:moi:Documents:31.12"


-- correct variable name
set thisName to "myFile"
my removeExtension(thisName) --> "myFile"

As you carefully worked upon the reverse of the original path, your code gave a correct result when a name contain several dots.
The problem is that if the name contains no dot and a folder name in the path contains such character, the result will be awful: the end of the folder name will be dropped with the file name.

I repeat that your choice of the variable name facilitate this kind of error.
If you were really passing a file name the problem wouldn’t strike

Back to the extraction of the name extension.
I dislike to write that but only the Finder make a correct job.

----------------------------------------------------------------
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
----------------------------------------------------------------

on getExtension:aFile
	set POSIXPath to POSIX path of aFile
	set pathNSString to current application's NSString's stringWithString:POSIXPath
	set theExt to pathNSString's pathExtension()
	return theExt as string
end getExtension:


set aFile to ((path to desktop as string) & "essai.jpeg") as alias

set theExt to name extension of (info for aFile) --> "jpeg"
log result
tell application "Finder" to set theExt to name extension of aFile --> "jpeg"
log result
tell application "System Events" to set theExt to name extension of aFile --> "jpeg"
log result
set theExt to my getExtension:aFile --> "jpeg"
log result

set aFile to ((path to desktop as string) & "essay") as alias

set theExt to name extension of (info for aFile) --> missing value which is correct but requires a 'special' treatment
log result
tell application "Finder" to set theExt to name extension of aFile --> ""
log result
tell application "System Events" to set theExt to name extension of aFile --> ""
log result
set theExt to my getExtension:aFile --> ""
log result


set aFile to ((path to desktop as string) & "essai.YK") as alias

set theExt to name extension of (info for aFile) --> "YK" which is WRONG
log result
tell application "Finder" to set theExt to name extension of aFile --> "" which is correct
log result
tell application "System Events" to set theExt to name extension of aFile --> "YK" which is WRONG
log result
set theExt to my getExtension:aFile --> --> "YK" which is WRONG
log result

As info for is deprecated for years, I’m not really bored by it’s behavior.
The behavior of System Events and ASObjC is more problematic.
With them, we must be sure of what we pass to them ends with a valid name extension.

YK is an acronym which I often use but it’s not a name extension.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 23 avril 2020 11:31:02

Thanks, Nigel – it was. I’ll edit accordingly (and get some sleep).

Thanks Yvan. Now I understand the original problem with my proposed solution code. It will not work if the filename does not have an extension (i.e. no period) and the path to the filename contains periods (or dots) (e.g one of the folders has a name with dots in it).

I also agree with you that it is better to just manipulate the filename and not the whole path including the filename. Working with the filename will help avoid a lot of problems.

In any event, it looks like I could fix my original code by checking whether the filename is missing an extension and deal with that case accordingly. For example:


on removeExtension(thisName)
	tell application "Finder"
		set theEXT to (name extension of thisName)
	end tell
	if theEXT is "" then
		set noExtName to thisName as string
	else
		set noExtName to (the reverse of every character of (thisName as string)) as string
		set x to the offset of "." in noExtName
		set noExtName to (text (x + 1) thru -1 of noExtName)
		set noExtName to (the reverse of every character of noExtName) as string
	end if
	return noExtName
end removeExtension

It appears to work with your test case (i.e. no filename extension but the path to the filename contains periods).

But your code is simpler and more elegant. It will probably run a lot faster too. (It also avoids coercion into strings!)

And thank you for taking the time to write your last example code. I never realized that there was a difference between a “name extension” and a “filename extension”. I always thought that they were the same. Your example using “assai.YK” shows that they are different.

I learned something new today! That is always a good thing.

Merci Beaucoup!

Robert
Quebec, Canada

It seems that I am unable to find the correct words.

Name extension is not a property of a file name, it’s a property of a file (aka a file path or a file reference)
Finder may get the name extension of an item which is a file descriptor.
It may be an alias like what is returned by choose file
or a Finder reference like what we get when we start from a selection.

tell application "Finder"
	set aFile1 to item 1 of (get selection)
	--> document file "P3110225.psd" of folder "Baudart YK" of folder "Desktop" of folder "**********" of folder "Users" of startup disk of application "Finder"
	set theExt1 to name extension of aFile1
	--> "psd"
	set aFile2 to (item 1 of (get selection)) as alias
	--> alias "SSD 1000:Users:**********:Desktop:Baudart YK:P3110225.psd"
	set theExt2 to name extension of aFile2
	--> "psd"
	
	set aFile3 to (item 1 of (get selection)) as «class furl»
	--> file "SSD 1000:Users:**********:Desktop:Baudart YK:P3110225.psd"
	try
		set theExt3 to name extension of aFile3
	on error errMsg number errNbr
		log errMsg & ",  number#" & errNbr
		--> (*Erreur dans Finder : Il est impossible d’obtenir name extension of file "SSD 1000:Users:**********:Desktop:Baudart YK:P3110225.psd".,  number#-1728*)
	end try
	
	set aName1 to name of aFile1
	try
		name extension of aName1
	on error errMsg number errNbr
		log errMsg & ",  number#" & errNbr
		--> (*Il est impossible d’obtenir name extension of "P3110225.psd".,  number#-1728*)
	end try
end tell

Maybe it’s more clear.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 23 avril 2020 17:15:14

Yes, human language can be vague and confusing.

But I believe I do understand you. in Applescript, the term “name extension” refers to a property of a file NOT to a property of the name of a file (or filename).

So you can only use “name extension” (typically within a Finder or System Events Tell Block) when one is dealing with files NOT names of files.

I will try to remember that. But maybe it is better to avoid using the Finder altogether! :slight_smile:

And “name extensions” are not the same as the extension of a file.

Using your example - assai.YK

YK is NOT a valid “name extension”. The name extension for assai.YK is “”.

But in my mind YK is an extension to the filename. It is just not a name extension.

Something has property in the programming only when it is object (1 special structure of code with properties, and methods). For example, string “Dog.txt” is not object, so the following will raise error:

properties of "Dog.txt"

the following returns result, but only because command item works here. It is not property:

item 1 of "Dog.txt" -- Result: "D"

NOTE: NSString @“Dog.txt” is object:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set aDog to current application's NSString's stringWithString:"Dog.txt" 
aDog's pathExtension() -- Result: "txt"

Here, used property pathExtension, which returns method pathExtension() of NSString class

Thanks KniazidisR.

Yes that makes sense. Only objects in programming have properties.

So going back to Yvan’s example. The “name” of a file is NOT an object so it does not have any properties.

But files are typically considered objects in programming. So files do have properties such as names, extensions etc.

Exactly, you understand me.

More specifically, AppleScript simple strings are also objects, only these are the simplest low-level objects. They have only one main method - the method that, when accessing an object, returns only 1, its value:

set anObject to a reference to "Dog.txt" -- Result: "Dog.txt"

But, anyway, it will be more correct to name an object only that which has some other properties and methods besides this main one.

How would you describe a filename like my old friend “31.12.43” which is perfectly correct?

On my machine there is not such filename because I NEVER urge the Finder to hide name extensions.

I repeat that, although I hate it, the Finder is the unique tool treating the name extensions correctly.

Info for is obsolete.
System Events and ASObjC assume that the last piece of a file name which is preceded by a dot is an extension. If I name a file : “La.guillotine”, guillotine will be treated as a name extension although it’s really not what it’s designed to achieve ???

Imagine a folder named “La.guillotine” passed erroneously in your original code. It would become La.JPG and I doubt that Preview would be at ease with it.

It’s important to understand that although AppleScript try to resemble to a natural language, it’s not one. Its vocabulary is made of words borrowed to natural languages but their meaning is not guaranteed to be exactly the common one.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 23 avril 2020 22:42:26

It’s not that simple, though. Suppose I write a new application, say Chop.app, and it saves its files as .guillotine files. guillotine is now a file extension – just not one defined in an app on your Mac (yet). By that argument, any extension not defined by the system or OS-installed apps is potentially not really an extension.

As you point out, the Finder’s scripting dictionary takes the stricter view. But most applications, and much of the system, take the opposite view – they use the approach Foundation uses because, well, they are built on Foundation. (FWIW, I suspect the Finder’s behavior is a hangover from the days of file types and creators, when extensions were entirely optional. In that world, it made sense.)

I think the real point here is that the whole notion of extensions is very fragile, and if you stray from the rule of always using them for documents, you’re asking for unpredictable results.

Hello Shane.

The Finder has a “logical behavior”. If the ending substring “describes the contents of the file”, it IS a name extension. In the other case, ITSN’T such object.
What is the interest of the object “name extension” if it is not guaranteed to be a “contents descriptor” ?

My grand daughter urged the Finder to never display the name extension. She also urged it to display windows with icons and to build them on the fly according to file’s contents. The result is that she never know which kind of file is in front of her.

My daughter made a more ‘logical’ choice. She hide name extensions but she display windows in columns mode so she see the fil type in its dedicated column.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 24 avril 2020 11:32:27

But how does the Finder know? You have a file called La.guillotine. How does it know I didn’t save the file from my Chop.app and send it to you?

@Shane
I’m sure that you know that but some readers may ignore it.
The Finder maintain a database of every name extension defined by the applications installed on the running machine.
As long of your application is not installed, “guillotine” is not identified as a name extension.
Such infos are given by the info.plist of every application in the array Exported Type UTIs.
For instance, in Preview’s plist, the first item of the array is the dictionary Item 0 (public radiance).
This dictionary contains a dictionary named Equivalent Types which itself contain an array of strings which are some of the name extensions which may be given to files exported by the app.
Here they are “pic”, “PIC”, “hdr”, “HDR”
In your app it would be “guillotine” (with perhaps its Uppercase version “GUILLOTINE”)
Complementary detail, if we uninstall the application, its set of extensions remains in the Finder’s database (the launchservices one if I remember well).

As System Events and Foundation are too lazy to use the informations available to both of them, they make no difference between a registered/identified extension and a standard string.

Jean-Paul Sartre wrote a play entitled “La P… respectueuse” (when he did we didn’t use ellipsis but 3 dots and France was ridiculous enough to refuse to write the word “Putain”)

If I saved a text file containing this play in old times, the file would have been named “La P… respectueuse” because in these old times Apple system didn’t use name extensions.
I have a lot of such old files and I never spent time to give them an extension.
As far as I know, nobody created an application using “respectueuse” as a name extension so, the Finder would be fair enough to know that the file has no extension.
The other tools, which may perfectly grab the info are too lazy to do that and would state that the file has the name extension “respectueuse” which is perfectly ridiculous and just prove their infamous laziness.

@KniazidisR
I apologize but I can’t check what you wrote.
I tried to urge the Finder to stop displaying name extensions.
I entered its Preferences pane and unchecked the dedicated checkbox and for safe, I rebooted
No luck, extensions were always displayed.
I entered the file com.apple.finder.plist and saw that the property AppleShowAllExtensions was set to YES. I edited it as NO, rebooted and extensions were always visibe.

The script below extracts the available settings and you will see that the results match what I wrote.

tell application "System Events" to tell process "Finder"
	set frontmost to true
	keystroke "," using {command down}
	class of UI elements --> {window, menu bar, scroll area}
	name of windows --> {"Préférences du Finder"}
	tell window 1
		class of UI elements --> {checkbox, checkbox, checkbox, checkbox, checkbox, checkbox, static text, pop up button, button, button, button, toolbar, static text}
		tell toolbar 1
			class of UI elements --> {button, button, button, button}
			name of buttons --> {"Général", "Tags", "Barre latérale", "Options avancées"}
			click button -1 --> "Options avancées"
		end tell --> toolbar 1
		class of UI elements --> {checkbox, checkbox, checkbox, checkbox, checkbox, checkbox, static text, pop up button, button, button, button, toolbar, static text}
		title of checkbox 1 --> "Afficher toutes les extensions de fichiers"
		value of checkbox 1 --> 0 -- unchecked
		title of checkbox 4 --> "Avertir avant de vider la corbeille"
		value of checkbox 4 --> 1 -- checked
	end tell
end tell

set showExtensions to do shell script "defaults read com.apple.finder AppleShowAllExtensions"--> "0"

If I ask the Finder for the properties of a file, I get something like:

{class:document file, name:"|ContentsStoreFormat%1$@_loc|.txt", index:263, displayed name:"|ContentsStoreFormat%1$@_loc|.txt", name extension:"txt", extension hidden:false, container:folder "Desktop" of folder "**********" of folder "Users" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{-1, -1}, desktop position:{1134, 768}, bounds:{-33, -33, 31, 31}, kind:"Document format texte", label index:0, locked:false, description:missing value, comment:"", size:674, physical size:4096, creation date:date "samedi 11 avril 2020 à  12:22:33", modification date:date "samedi 11 avril 2020 à  12:22:33", icon:missing value, URL:"file:///Users/**********/Desktop/%7CContentsStoreFormat%251$@_loc%7C.txt", owner:"**********", group:"(inconnu)", owner privileges:read write, group privileges:read only, everyones privileges:read only, file type:missing value, creator type:missing value, stationery:false, product version:"", version:""}

I may live with a system behaving this way but if you tell me what I must do to really stop the extensions display I would be glad to check how it behaves at script level.
Of course, after doing that I would return to my standard settings.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 24 avril 2020 15:11:06

This point has been made above, but I ran a simple test just to confirm my understanding and thought I would report the results.

I created two files with the following names: “Test File.txt” and “Test File.xxx”. I then ran the following scripts and received the results shown:

tell application "Finder"
	name extension of file "Macintosh HD:Users:Robert:Test File.txt" --> "txt"
	name extension of file "Macintosh HD:Users:Robert:Test File.xxx" --> ""
end tell

tell application "System Events"
	name extension of file "Macintosh HD:Users:Robert:Test File.txt" --> "txt"
	name extension of file "Macintosh HD:Users:Robert:Test File.xxx" --> "xxx"
end tell

So, at least in this case, Finder was able to distinguish an invalid file extension and System Events was not. I ran these tests twice–first with the file extensions visible in the Finder and then with the file extensions hidden. The results did not change from those shown above.

I discovered a funny thing.
Most of my files appear with their name extension but some don’t.
In a given folder
16 .numbers doc have their extension, 4 haven’t
2 .pages documents have their extension, 3 haven’t
20 applets/droplets have no extension
every pdf or rtf files have their extension
50 .scpt files have their extension, one hasn’t
15 .applescript files have their extension, one hasn’t

I can’t guess what is the logic at work in such behavior.
As I’m curious I ran a test file.

set aFile to (choose file) as alias

tell application "Finder"
	properties of aFile --> {class:document file, name:"Chèques YK 2019.numbers", index:9, displayed name:"Chèques YK 2019", name extension:"numbers", extension hidden:true, container:folder "ƒ banque" of folder "Important" of folder "Documents" of folder "**********" of folder "Users" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{592, 22}, desktop position:missing value, bounds:{560, -10, 624, 54}, kind:"Feuille de calcul Numbers", label index:0, locked:false, description:missing value, comment:"", size:582932, physical size:618496, creation date:date "lundi 13 mai 2019 à  15:59:54", modification date:date "vendredi 24 avril 2020 à  15:44:00", icon:missing value, URL:"file:///Users/**********/Documents/Important/%C6%92%20banque/Che%CC%80ques%20YK%202019.numbers", owner:"**********", group:"(inconnu)", owner privileges:read write, group privileges:read only, everyones privileges:read only, file type:missing value, creator type:missing value, stationery:false, product version:"", version:""}
end tell

And what I see doesn’t match KniazidisR’s statements (but am’I really surprised by that?).
The name of the file has its extension “numbers”.
The extension “numbers” is perfectly returned.
The extension is described as hidden.
The displayed name is correctly deprived of the extension.

I ran an expanded version of the KniazidisR’s script:


property openTypes : {"PDF", "com.adobe.pdf", "BMP", "com.microsoft.bmp", "PICT", "com.apple.pict", "PNG", "public.png", "PSD", "com.adobe.photoshop-image", "TIFF", "public.tiff"}

--Get the artwork file
set theFiles to choose file with prompt "Choose art file(s)" of type openTypes with multiple selections allowed without invisibles
set theType to "JPG"

repeat with aFile in theFiles
	runTest(aFile, theType)
end repeat

on runTest(theArt, theType)
	log "theArt is " & theArt
	tell application "Finder"
		set theFolder to (container of theArt) as text
		set visiName to displayed name of theArt
		set theNewArt to theFolder & (name of theArt) & "." & theType
	end tell
	log "visible name is " & visiName & ", theNewArt is " & theNewArt & linefeed
end runTest

and what I got doesn’t match KniazidisR’s statements.
Note that the 1st and 3rd items have their extension visible, the 2nd one has its extension hidden although the 3 aliases appear with their extension.

tell application "Script Editor"
	choose file with prompt "Choose art file(s)" of type {"PDF", "com.adobe.pdf", "BMP", "com.microsoft.bmp", "PICT", "com.apple.pict", "PNG", "public.png", "PSD", "com.adobe.photoshop-image", "TIFF", "public.tiff"} with multiple selections allowed without invisibles
		--> {alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf", alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf", alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf"}
end tell

(*theArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf*)
tell application "Finder"
	get container of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf"
		--> "SSD 1000:Users:**********:Documents:Important:ƒ banque:"
	get displayed name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf"
		--> "2018-11-23 Taxe habitation Roquesteron.pdf"
	get name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf"
		--> "2018-11-23 Taxe habitation Roquesteron.pdf"
end tell
(*visible name is 2018-11-23 Taxe habitation Roquesteron.pdf, theNewArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-11-23 Taxe habitation Roquesteron.pdf.JPG
*)   WHICH IS WRONG

(*theArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf*)
tell application "Finder"
	get container of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf"
		--> "SSD 1000:Users:**********:Documents:Important:ƒ banque:"
	get displayed name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf"
		--> "2018-12-13"
	get name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf"
		--> "2018-12-13.pdf"
end tell
(*visible name is 2018-12-13, theNewArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:2018-12-13.pdf.JPG
*)  WHICH IS WRONG

(*theArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf*)
tell application "Finder"
	get container of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf"
		--> "SSD 1000:Users:**********:Documents:Important:ƒ banque:"
	get displayed name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf"
		--> "attestation tva 10%.pdf"
	get name of alias "SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf"
		--> "attestation tva 10%.pdf"
end tell
(*visible name is attestation tva 10%.pdf, theNewArt is SSD 1000:Users:**********:Documents:Important:ƒ banque:attestation tva 10%.pdf.JPG
*)  WHICH IS WRONG

Important feature, the authoring application name its documents and its windows according to the Finder’s displayed name.

set aFile to ((path to documents folder as string) & "Important:ƒ banque:Chèques YK 2019.numbers") as «class furl»
tell application "Numbers"
	open aFile
	name of window 1 --> "Chèques YK 2019"
	tell document 1
		its name --> "Chèques YK 2019"
		its file --> file "SSD 1000:Users:**********:Documents:Important:ƒ banque:Chèques YK 2019.numbers"
		its modified --> false
	end tell
end tell

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) vendredi 24 avril 2020 16:52:26

I made a mistake in my testing. I tried giving the folder an extension and tried to trick Finder or System Events hiding the extension. So, I gave the wrong information - I “can deceive” System Events, not Finder. That is, the opposite is true. Just the System Events takes the text after the dot as name extension, is it hidden or now. Testing the same with file, both Finder and System Events returns trust result.

That is, it is better not to argue about name extensions with Finder. :rolleyes: Makes sense to delete my previous post so as not to mislead users anymore. It turns out that not this Finder behaviour is harmful to health, but namely my previous post…

Don’t forget I don’t apply this new name to the real file yet. So, it is true.

Yvan,

The database (part of Launch Services) is not maintained by the Finder – it is consulted by the Finder – that’s how it knows what application to use when you double-click on a document.

Your characterisation of other approaches as lazy is incorrect: it’s a deliberate policy. Extensions are defined variously in system documentation as that text that follows the last . in a file name. They are not limited to those registered in a user’s Launch Services database.