Skip to content

Instantly share code, notes, and snippets.

@seignovert
Last active August 15, 2024 10:47
Show Gist options
  • Save seignovert/f2dc917dc2b8ebbd62195fee5c12f231 to your computer and use it in GitHub Desktop.
Save seignovert/f2dc917dc2b8ebbd62195fee5c12f231 to your computer and use it in GitHub Desktop.
[macOS] Set Icon to a File/Folder

Set Icon to a File / Folder on macOS

Since macOS High Sierra sips --addIcon is no longer supported. An easier way to add and image to a file/folder is to use fileicon npm package.

The new syntax is:

fileicon set foo img.png

The old method setIcon is kept here a an archive:

Extract icon from PNG image

Take an image and make the image its own icon:

sips -i icon.png

Extract the icon to its own resource file:

DeRez -only icns icon.png > tmpicns.rsrc

For a file

Append this resource to the file you want to icon-ize.

Rez -append tmpicns.rsrc -o file.ext

Use the resource to set the icon.

SetFile -a C file.ext

For a folder

Append a resource to the folder you want to icon-ize.

Rez -append tmpicns.rsrc -o $'myfolder/Icon\r'

Use the resource to set the icon.

SetFile -a C myfolder/

Hide the Icon\r file from Finder.

SetFile -a V $'myfolder/Icon\r'

Clean up.

rm tmpicns.rsrc

Source: Stackexchange

#!/bin/bash
# Set Icon to a File / Folder on macOS
icon=$1
dest=$2
# Check inputs
if [ "$#" -ne 2 ]; then
echo "USAGE: $(basename $0) icon.png File|Folder"
exit 1
elif [ ! -f $icon ]; then
echo "ERROR: File $1 does not exists"
exit 1
elif [[ ! $icon =~ .*\.(png|PNG|jpg|JPG) ]]; then
echo "ERROR: Icon must be a .png|.jpg file"
exit 1
elif [ -f $dest ]; then
folder=false
elif [ -d $dest ]; then
folder=true
else
echo 'ERROR: File|Folder destination does not exists'
exit 1
fi
# Create icns icon
sips -i $icon > /dev/null
DeRez -only icns $icon > /tmp/tmpicns.rsrc
# Set Icon
if [ "$folder" = true ]; then
Rez -append /tmp/tmpicns.rsrc -o $dest$'/Icon\r'
SetFile -a C $dest
SetFile -a V $dest$'/Icon\r'
else
Rez -append /tmp/tmpicns.rsrc -o $dest
SetFile -a C $dest
fi
# Clean up
rm /tmp/tmpicns.rsrc
exit 0
@FradSer
Copy link

FradSer commented Jun 29, 2019

Now at macOS 10.14, you just need below:

sips -s format icns Icon.png --out tmpicns.icns
echo "read 'icns' (-16455) \"tmpicns.icns\";" >> tmpicns.rsrc
Rez -a tmpicns.rsrc -o file.ext
SetFile -a C file.ext

@Peter-Schorn
Copy link

Now at macOS 10.14, you just need below:

sips -s format icns Icon.png --out tmpicns.icns
echo "read 'icns' (-16455) \"tmpicns.icns\";" >> tmpicns.rsrc
Rez -a tmpicns.rsrc -o file.ext
SetFile -a C file.ext

Could you explain this code in more detail? It seems to me like this code sets a custom icon for a file/folder. Is this correct?

@FradSer
Copy link

FradSer commented Jan 9, 2020

@Peter-Schorn
Copy link

@FradSer Ok, I got it to work for files, but how to I set icons for directories?

@microbians
Copy link

microbians commented Aug 25, 2020

The is some kind of a bug with the change of icons of "folders" nor files, al last in Catalina. When the Icon change it does not refresh in the UI when the folder have a custom older icon set.

By looking to a workaround, found this little fix (no ideal but works): - this is in JXA Javascript for automation

> function makeIcon(theFolder, theFile) {
> 	var img = $.NSImage.alloc.initByReferencingFile( theFile ); // Allocs the image you wanna use as Icon it will resize to an square
> 
> 	var pathToFolderContainer = theFolder.substring(0, theFolder.lastIndexOf("/")); / The folder contains the folder you wana change the icon
> 	var nameOfFolder = theFolder.substring(theFolder.lastIndexOf("/")+1); // Get the name of the folder you wanna change the icon
> 	
> 	var uniqueID = ""+newUUID(); // Create a unique ID
> 
> 	terminal("mv "+ sanityzeForBash(theFolder)+" "+ sanityzeForBash(pathToFolderContainer+"/"+uniqueID)); // Rename the folder to the uniqueID
> 	terminal("mkdir "+ sanityzeForBash(theFolder)); // Create a new and clean folder (with the original name)
> 
> 	$.NSWorkspace.sharedWorkspace.setIconForFileOptions(img, theFolder, 0); // Set the icon on the new folder (empty folder with the original name)
> 
> 	terminal("echo -n > "+ sanityzeForBash(pathToFolderContainer+"/"+uniqueID+"/Icon\r")); // Reset the Icon on the old folder
> 	terminal("rm "+ sanityzeForBash(pathToFolderContainer+"/"+uniqueID+"/Icon\r")); // Delete the Icon on the old folder
> 	terminal("(shopt -s dotglob; mv "+sanityzeForBash(pathToFolderContainer+"/"+uniqueID+"\/\*")+" "+sanityzeForBash(theFolder+"/")+")");  // Move all the content form the old to the new folder
> 	terminal("rm  -r "+ sanityzeForBash(pathToFolderContainer+"/"+uniqueID)); // Delete the old (now empty folder)
> 
> 	$.NSWorkspace.sharedWorkspace.noteFileSystemChanged(theFolder); // This is not necessary but...
> }
> function sanityzeForBash(s) {
>  	return s.split(" ").join("\\ ");
> }
> function newUUID(){
>     return ObjC.unwrap($.NSUUID.UUID.UUIDString);
> }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment