How to change a folder icon ?

Thank you, installed it and no error anymore

beautiful applescript; was looking for this functionality in applescript, started writing my own but didn’t get very far due the lack of sufficient knowlegde

but i applied it to my music folder, in which every folder contains a jpg-file, but not every folder get an icon

i understand that the script takes the first jpg which the folder contains, but apparently there must be a difference somewhere

Edit: I found the difference, the jpg files contain special symbols like é and ü etc…

thx very much

Hello, this is a very old topic but I have just tried this script and it gives me an error

error “missing value doesn’t understand the “save” message.” number -1708 from missing value

on line

save with icon – save icon_image_file with itself as icon

Hoping someone can help as I am very new to AppleScript

Thanks,
Rob

Hi @rob71. Welcome to MacScripter.

It seems that the Image Events application in macOS no longer understands AppleScript’s ‘alias’ specifier, which is what’s passed to the saveImageWithItselfAsIcon(F) handler in Yvan’s script. The simplest fix seems to be to change this line in the handler:

tell (open F)

to:

tell (open (F as «class furl»))

This coerces the alias to a different kind of file specifier that Image Events does understand and can use to open the image file.

The script in the post to which you’ve replied depends on a third-part utility called “osxutils” which has to be downloaded and installed before it can be used. The URL for it in the script’s comments now appears to be dead, which isn’t totally surprising after 17 years! Google returns several hits for the name, but I haven’t checked any of them out to see if they’re the same utility and work with current versions of macOS. The other scripts in this thread don’t need it.

Hi Nigel, and thanks for your help! The script I was trying to use was the one Yvan posted before the one requiring osxutils. I have amended the line that was causing the error, but it is still not producing the intended result (i.e pointing at a folder, if an image is present then use that image as the folder icon, any subfolders containing their own image use this image for the folder icon, any subfolders without an image file use the image in the parent folder as their icon). It doesn’t actually change the icon to the image expected, it just creates an icon of a generic ‘‘jpeg’’ icon; and any subfolders are ignored. Sometimes it will complete without an error, but if pointing the script to a folder containing several subfolders it will produce a time-out error.
As I say I am just at the start of my journey with AppleScript so it is all beyond me at present, but grateful for any advice you can give (as from the comments it seemed to work on older versions of MacOS).

Hi rob71.

I’ve run the script right through with a test folder this morning and it turns out that there’s been a change in the Finder’s behaviour too which essentially renders Yvan’s ingenious workaround useless. :confused: Also, the script was never intended to change the icon for folders not containing an image file. Its modus operandi is:

  • Search the current folder for any image files — specifically JPEG ones.
  • If there are any:
    • Use Image Events to open the first one found and to resave it immediately with the image it contains as its icon. This still works once the ‘alias’ business is sorted out.
    • Open a Finder information window for the image file and copy the icon from it to the clipboard. This still works, BUT the icon shown in the information window is now the generic one for an image file, not the actual icon assigned to the file. Or I should say: in many cases, the icon’s a generic one. On both my Ventura and Sequoia machines, my testing so far has shown that only image file icons are genericised (if that’s a word) and only some image files are so affected. I’ve not so far been able to determine what sets affected and unaffected image files apart. It doesn’t seem to be related to size, age, colourisation, or dimensions.
    • Open a Finder information window for the current folder and paste the copied icon image into it. This sets the icon for the folder. (An invisible file whose name is (“Icon” & return) is saved in the folder.)
  • Recursively repeat the above with any subfolders, subfolders of subfolders, etc.

So I don’t know the answer at the moment. I’ll look into it further, and hopefully others will be inspired to do so too, but for now I’m stumped. :frowning:

1 Like

Hi peavine.

Yes. It seems to. When I apply your script to my test hierarchy, which contains one or two subfolders that don’t contain JPEG files, it complains that the folder is empty and only offers the option to stop. None of the folders’ icons are changed. It does work though with a folder containing a JPEG and no subfolders. And using ASObjC to handle the icons is definitely the way to go!

1 Like

Thanks Nigel for your explanation. I misunderstood the OP’s requirements, confusing the folder selected by the user with the parent folder. This raises the question as to what should happen if a subfolder does not have a JPG and that subfolder’s parent folder does not have a JPG. Do you just keep going up the path until you find a JPG?

1 Like

Hi peavine.

As I understand it from rob72’s description above (I expect he’ll clarify it himself later), he wants every folder in the chosen hierarchy that contains a JPEG file to have an icon that’s the same picture as the one in that file. If a folder doesn’t contain a JPEG file, he wants that folder to have the same icon as the one given to the chosen root folder. Yvan’s scripts do something similar except that folders not containing JPEGS aren’t given new icons. It may be a good idea to wait for rob72 to confirm what he wants before getting too deeply into the code development! I won’t be able to do anything about it myself for the next day or so, so I’ll leave it to your expertise with NSIcon methods!

2 Likes

Hi Nigel, that is exactly what I’m hoping to achieve, thank you. In the case that a subfolder does not have an image file (it could be a jpg or a png) my goal is that the subfolder inherits the same icon image as its parent folder.

Thanks Nigel. I’ve included below a script that works in the above fashion. Please note that the user is notified of an error and the script stops if the chosen root folder does not contain a JPG file. I tested this script on my Sequoia computer without issue.

use framework "AppKit"
use framework "Foundation"
use scripting additions

on main()
	set allowedSubfolders to 10 --set to desired value
	set theFolder to POSIX path of (choose folder)
	set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
	set folderImage to getImage(theFolder)
	if (folderImage's |count|()) is 0 then display dialog "This script cannot proceed because a JPG file was not found in the chosen root folder." buttons {"OK"} cancel button 1 default button 1
	set folderImage to folderImage's objectAtIndex:0
	set theSubfolders to getSubfolders(theFolder)
	set subfolderCount to theSubfolders's |count|()
	if subfolderCount is greater than or equal to allowedSubfolders then display dialog "This script cannot proceed because the chosen root folder contains " & subfolderCount & " subfolders, which exceeds the allowed number of subfolders." buttons {"OK"} cancel button 1 default button 1
	display dialog "The chosen root folder contains " & subfolderCount & " subfolders. Do you want to change the icon of the chosen root folder and all of its subfolders? An existing Finder window may have to be closed and reopened to see the changed icons." cancel button 1 default button 1
	set folderImage to (current application's NSImage's alloc()'s initWithContentsOfURL:folderImage)
	(current application's NSWorkspace's sharedWorkspace()'s setIcon:folderImage forFile:(theFolder's |path|()) options:2)
	repeat with aSubfolder in theSubfolders
		set subfolderImage to getImage(aSubfolder)
		if (subfolderImage's |count|()) is 0 then
			set subfolderImage to folderImage
		else
			set subfolderImage to (current application's NSImage's alloc()'s initWithContentsOfURL:(subfolderImage's objectAtIndex:0))
		end if
		(current application's NSWorkspace's sharedWorkspace()'s setIcon:subfolderImage forFile:(aSubfolder's |path|()) options:2)
	end repeat
end main

on getSubfolders(theFolder)
	set fileManager to current application's NSFileManager's defaultManager()
	set folderKey to current application's NSURLIsDirectoryKey
	set packageKey to current application's NSURLIsPackageKey
	set folderContents to (fileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:6 errorHandler:(missing value))'s allObjects()
	set theSubfolders to current application's NSMutableArray's new()
	repeat with anItem in folderContents
		set {theResult, aFolder} to (anItem's getResourceValue:(reference) forKey:folderKey |error|:(missing value))
		if aFolder as boolean is true then
			set {theResult, aPackage} to (anItem's getResourceValue:(reference) forKey:packageKey |error|:(missing value))
			if aPackage as boolean is false then (theSubfolders's addObject:anItem)
		end if
	end repeat
	return theSubfolders
end getSubfolders

on getImage(theFolder)
	set fileManager to current application's NSFileManager's defaultManager()
	set folderContents to fileManager's contentsOfDirectoryAtURL:(theFolder) includingPropertiesForKeys:{} options:4 |error|:(missing value)
	set thePredicate to current application's NSPredicate's predicateWithFormat:"pathExtension ==[c] 'jpg'"
	return (folderContents's filteredArrayUsingPredicate:thePredicate)
end getImage

main()
1 Like

It works well on both my Sequoia and Ventura machines. :sunglasses:

1 Like