How can I change or set the icon for a file or folder, in the terminal, do I need to use a scripting language?
- See also sveinbjorn.org/osxiconutilsuser588– user5882012-05-12 09:36:52 +00:00Commented May 12, 2012 at 9:36
- 1Note that it does not scale well. Tried to apply icons to lots of directories in one directory — Finder worked very slow.kolen– kolen2015-04-28 13:28:56 +00:00Commented Apr 28, 2015 at 13:28
13 Answers
You'll need the Developer Tools installed, and then the following might work. This takes the graphic in icon.png and applies it to file.ext.
# Take an image and make the image its own icon: sips -i icon.png # Extract the icon to its own resource file: /Developer/Tools/DeRez -only icns icon.png > tmpicns.rsrc # append this resource to the file you want to icon-ize. /Developer/Tools/Rez -append tmpicns.rsrc -o file.ext # Use the resource to set the icon. /Developer/Tools/SetFile -a C file.ext # clean up. rm tmpicns.rsrc # rm icon.png # probably want to keep this for re-use. - Awesome, that's just what I wanted.ocodo– ocodo2011-01-24 23:56:33 +00:00Commented Jan 24, 2011 at 23:56
- I'm having trouble with
Rez -appendwhen working with.avifiles.### Rez - Fatal error trying to open the resource file "Video.avi" for writing.` any ideas?ocodo– ocodo2011-01-26 11:24:17 +00:00Commented Jan 26, 2011 at 11:24 - Interestingly, it also made the file unable to accept a new icon via the Get Info copy/paste method.ocodo– ocodo2011-01-26 19:06:53 +00:00Commented Jan 26, 2011 at 19:06
- is there a restriction on the icon size? If I use a large jpg (1024x768) it would be resized to something really small.. Can I somehow retain its original size?nuc– nuc2011-03-13 19:21:29 +00:00Commented Mar 13, 2011 at 19:21
- 6Note that in recent OSX versions the developer tools are in the
$PATH(stubs in/usr/binthat know where to find the actual tools), and not in/Developer/Toolsanymore, so you should invoke them just by their filenames; i.e., in the case at hand, as justRezandDeRez.mklement0– mklement02015-07-31 21:13:04 +00:00Commented Jul 31, 2015 at 21:13
With the benefit of several years of hindsight:
user588's answer and koiyu's answer work well, but they rely on utilities (Rez, DeRez, and SetFile) that:
- are not installed by default (they come with either Xcode or the developer command-line utilities)
- are now deprecated (
RezandDeRez, because they relate to Carbon)
The osxiconutils project looks interesting, but is no longer maintained and won't compile any longer (as of macOS 10.10.4).
- velkoon points out that the linked repo offers downloading a ZIP file with (x64) binaries that still work as of macOS 13 (Ventura). You'll have to authorize the binaries for local execution by running the following against the ZIP file before extracting its contents:
xattr -d com.apple.quarantine osxiconutils.zip. - A notable limitation of the
seticonutility is that it can only assign.icnsfiles, not also other image formats - unlike thefileiconutility discussed below.
Therefore I've created CLI fileicon, which should work on a pristine macOS machine (no prerequisites); it is a Bash script based primarily on xattr, xxd and an embedded Python script that calls Cocoa, courtesy of this helpful answer. [Update: Since Python no longer comes with macOS, the Python script has been replaced with an ObjC Bridge AppleScript.]
It allows setting/removing/extracting custom icons for/from files or folders, including on APFS volumes on macOS 10.13 (High Sierra). [Update: Still works as of macOS 13, Ventura.]
You can install it as follows:
If you have Homebrew installed:
brew install fileiconIf you have Node.js installed, from the npm registry, with
[sudo] npm install -g fileiconOtherwise:
- Download the CLI as
fileicon(this link will stay current). - Make it executable with
chmod +x fileicon.- Move it or symlink it to a folder in your
$PATH, such as/usr/local/bin(requiressudo).
- Move it or symlink it to a folder in your
- Download the CLI as
Here's the usage information; for complete information, refer to the manual:
$ fileicon -h Set a custom icon for a file or folder: fileicon set <fileOrFolder> <imageFile> Remove a custom icon from a file or folder: fileicon rm <fileOrFolder> Get a file or folder's custom icon: fileicon get [-f] <fileOrFolder> [<iconOutputFile>] Test if a file or folder has a custom icon: fileicon test <fileOrFolder> -q ... silence status output Standard options: --help, --man, --version, --home - @Slomojo: [In response to a since-deleted comment] I get that not everybody has or wants to install Node.js, that's why the direct download link is there as well (see the 'Otherwise:` list item in my answer) - it's a self-contained Bash script (the only thing you forgo by installing this way is installation of the man page, but you can get a plain-text rendering of the manual page with
fileicon --man).mklement0– mklement02015-08-04 03:34:14 +00:00Commented Aug 4, 2015 at 3:34 - 6This is a nice out of the box working solution. +1user3439894– user34398942016-02-28 00:48:58 +00:00Commented Feb 28, 2016 at 0:48
- 3I realize I'm a few years behind everyone else on this thread, but just wanted to mention that I discovered this today and it's great. Thank you for making it! 👍TJ Luoma– TJ Luoma2019-09-20 18:18:11 +00:00Commented Sep 20, 2019 at 18:18
- 1Works very wellZlatko-Minev– Zlatko-Minev2021-02-18 04:29:00 +00:00Commented Feb 18, 2021 at 4:29
- 1
I almost started a bounty on this, because I didn't manage to change the icon of a folder using @mankoff's answer. But I found a solution.
To change folder's icon you don't point Rez -append tmp.rsrc to the folder but a special Icon\r file inside the folder. If you haven't set a custom icon to the folder before, the file probably will not exist, but Rez creates it on–the–fly. Deleting the Icon\r file will remove the custom icon, so to prevent accidents it is good to be hidden.
These are the modifications to the mankoff's answer:
# 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' - And for a file? Note my comment re: avi filesocodo– ocodo2011-03-12 02:27:15 +00:00Commented Mar 12, 2011 at 2:27
- @slomojo sorry, but I can't replicate the error you get—just tested the mankoff's solution with an .avi file. Re-check the file permissions and commands you entered?Jari Keinänen– Jari Keinänen2011-03-15 09:20:37 +00:00Commented Mar 15, 2011 at 9:20
- I'll give it another go, perhaps I made a mistake before.ocodo– ocodo2011-03-15 11:22:26 +00:00Commented Mar 15, 2011 at 11:22
- I am desperately trying to do this for a USB thumb drive. All of the commands "work" in that they don't return errors, but I am still left with a thumb drive with an unchanged icon. Any thoughts and I'd be eternally grateful!singmotor– singmotor2015-08-07 19:59:50 +00:00Commented Aug 7, 2015 at 19:59
In addition to Ruby, here's a Python version:
#!/usr/bin/env python import Cocoa import sys Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(Cocoa.NSImage.alloc().initWithContentsOfFile_(sys.argv[1].decode('utf-8')), sys.argv[2].decode('utf-8'), 0) or sys.exit("Unable to set file icon") ./set-image.py image.png myfile
Python that pre-installed in Mac OS already has PyObjC so you don't have to install any packages.
- I added decoding of UTF-8 to unicode, otherwise script not worked with non-ASCII filenames. Also added check of return value, failure to set icon will result in return code of 1.kolen– kolen2014-12-15 21:21:28 +00:00Commented Dec 15, 2014 at 21:21
- 1Is there anyway we can specify the icon not have aspect ratio modified? It works great, but image files get reshaped to a square. Thanks!Gustavo Bezerra– Gustavo Bezerra2015-04-28 01:29:30 +00:00Commented Apr 28, 2015 at 1:29
- 1Didn't exactly find the answer, but squaring the images with transparent padding before hand worked just fine: stackoverflow.com/questions/12179342/…Gustavo Bezerra– Gustavo Bezerra2015-04-28 01:55:48 +00:00Commented Apr 28, 2015 at 1:55
- I understand that on macOS Big Sur release, python will be removed. Would this still work?ariestav– ariestav2020-10-07 21:44:41 +00:00Commented Oct 7, 2020 at 21:44
Check out setfileicon (source code), an utility created by Damien Bobillot.
Download the binary here: http://maxao.free.fr/telechargements/setfileicon.gz
After unpacking the file, make it executable:
chmod +x setfileicon Then you can use it as follows:
./setfileicon "my-icon.icns" "my-file-or-directory" I have a github project where I create AppleScript "droplets" from [shell/bash, python, perl, ruby, etc.] scripts that take file paths as arguments. I wrote this bash function for changing the icon of an folder (because AppleScript bundles are Folders with a .app extension).
replace_icon(){ droplet="$1" icon="$2" if [[ "$icon" =~ ^https?:// ]]; then curl -sLo /tmp/icon "$icon" icon=/tmp/icon fi rm -rf "$droplet"$'/Icon\r' sips -i "$icon" >/dev/null DeRez -only icns "$icon" > /tmp/icns.rsrc Rez -append /tmp/icns.rsrc -o "$droplet"$'/Icon\r' SetFile -a C "$droplet" SetFile -a V "$droplet"$'/Icon\r' } Once defined, you call the function with 2 arguments:
replace_icon /path/to/AppleScript.app /path/to/icon.png or
replace_icon /path/to/AppleScript.app http://i.imgur.com/LmUvWqB.png As you can see the second argument can be an image on your system, or a URL.
NOTE: That crazy looking $'/Icon\r' thing that I do is because the name of the Icon file ends with a literal carriage return \r. See for yourself with:
find my-applescript.app -maxdepth 1 | less -U Assuming that we have icns-file already. Create temp resource file which points to icns-file:
$ echo "read 'icns' (-16455) \"Icon.icns\";" >> Icon.rsrc Append the resource file as value of extended attribute "com.apple.ResourceFork" to a file:
$ Rez -a Icon.rsrc -o FileName.ext Show the icon of the file:
$ SetFile -a C FileName.ext Append resource file as value of extended attribute "com.apple.ResourceFork" to a magic icon file inside current folder:
$ Rez -a Icon.rsrc -o Icon$'\r' Show the icon of current folder:
$ SetFile -a C . Hide the magic icon file inside current folder (press ⇧⌘. to show/hide hidden files in Finder):
$ SetFile -a V Icon$'\r' Additional details
Icon data is stored as value of extended attribute "com.apple.ResourceFork" (Terminal command "xattr -p com.apple.ResourceFork FileName.ext" prints the value). For a folder there is magic (which is empty and hidden) file Icon$'\r' inside the folder. To extract icon data from extended attribute "com.apple.ResourceFork" into plain text resource file (from which we know correct icns-type identifier "-16455"):
$ DeRez -only icns FileWithIcon.ext > Icon.rsrc $ DeRez -only icns /Folder/With/Icon/Icon$'\r' > Icon.rsrc Under macOS 10.13 High Sierra command $ sips -i ImageFile.icns/png/jpg generates error "--addIcon is no longer supported". Switch "-i" means "--addIcon" as extended attribute "com.apple.ResourceFork" onto this file itself using the content of this image file.
- #<stdin>:1: ### /Applications/Xcode.app/Contents/Developer/usr/bin/Rez - SysError 0 during read.quanta– quanta2019-01-30 13:50:04 +00:00Commented Jan 30, 2019 at 13:50
Another option is to use MacRuby:
/usr/local/bin/macruby -e 'framework "Cocoa";NSWorkspace.sharedWorkspace.setIcon(NSImage.alloc.initWithContentsOfFile("/tmp/a.png"),forFile:"/tmp/file",options:0)'
You can download an installer for MacRuby from http://macruby.org.
- 1The link - and MacRuby - are apparently now dead; MacRuby was apparently succeeded by the commercial, subscription-based RubyMotion.mklement0– mklement02015-07-30 21:25:39 +00:00Commented Jul 30, 2015 at 21:25
Strangely enough the best solution seems to be not to use Apple's own tools but the Python code because it has various advantages not being limited by:
- output file resolution
(it works till 1024x1024) - input file format
(tried with ICNS and PNG) - permissions to install
(define it as a function)
Update
Now (on macOS Sierra) @koiyu’s answer seems to work, so you could use this two-liner to copy the icon from a source folder to your destination folder:
#!/bin/sh DeRez -only icns $1/Icon$'\r' > icon.rsrc; Rez -a icon.rsrc -o $2/Icon$'\r' SetFile -a C $2; SetFile -a V $2/Icon$'\r'; rm icon.rsrc - Welcome to Ask Different! This seems like it would be better as a comment. I know you don't have the points required yet, but I've asked someone who has the power to come take a look. In addition, I've written an Applescript that does all this for you in a neat bundle, see my answer to a similar question on this SE.JMY1000– JMY10002016-05-20 02:04:30 +00:00Commented May 20, 2016 at 2:04
- Yes, I tried but could not do it. Furthermore I think that the 2nd part of your comment would be better as an answer, not being related to the 1st one.dardo82– dardo822016-05-22 02:41:12 +00:00Commented May 22, 2016 at 2:41
Much like the Python solution using PyObjC, it turns out it can be done with just AppleScript (which isn't deprecated in 10.15 Catalina, unlike Python and other scripting languages).
I found an example of how to do this on GitHub here:
#!/usr/bin/env osascript use framework "AppKit" -------------------------------------------------------------------------------- # PROPERTY DECLARATIONS: property this : a reference to current application property NSWorkspace : a reference to NSWorkspace of this property NSImage : a reference to NSImage of this -------------------------------------------------------------------------------- # IMPLEMENTATION: on run argv set icon to item 1 of argv set target to item 2 of argv setIcon to icon for target end run -------------------------------------------------------------------------------- # HANDLERS: to setIcon to iconPath for filePath set sharedWorkspace to NSWorkspace's sharedWorkspace() set newImage to NSImage's alloc() set icon to newImage's initWithContentsOfFile:iconPath set success to sharedWorkspace's setIcon:icon forFile:filePath options:0 end setIcon
AppleScript isn't easy to read, but apparently it's possible to access the Objective-C code to do this through the AppKit framework.
- Thats great. Thank you very much. I was even be able to run this script from Java-Code and it works perfectly fine.Philipp Li– Philipp Li2020-05-07 08:16:57 +00:00Commented May 7, 2020 at 8:16
In the recent macOS version (10.14), sips -i icon.png will get a --addIcon is no longer supported error.
It also needs Developer Tools installed. This uses the graphic in Icon.png and applies it to file.ext, just like user588's answer:
# Covert Icon.png to tmpicons.icns: sips -s format icns Icon.png --out tmpicns.icns # Create temporary resource file which points to tmpicons.icns: echo "read 'icns' (-16455) \"tmpicns.icns\";" >> tmpicns.rsrc # append this resource to the file you want to icon-ize. Rez -a tmpicns.rsrc -o file.ext # Use the resource to set the icon. SetFile -a C file.ext # Clean up rm tmpicons.icns && rm tmpicns.rsrc - I get
Error: Unable to write image to file /Users/uname/tmpicns.icns.4rzX6on the first command. I even try withsudo, not workleetbacoon– leetbacoon2019-12-07 09:48:10 +00:00Commented Dec 7, 2019 at 9:48 - I got the same issue as @leetbacoon . Anyone know why?Peter Schorn– Peter Schorn2020-01-09 22:06:06 +00:00Commented Jan 9, 2020 at 22:06
- @leetbacoon See blog.macsales.com/… for info on how to convert an iconset folder to an icns file. If you need to programmatically create the iconset folder and populate it with png files, use
sips -z x x input.png -o output.pngwhere x is the height and width of the image, respectively. This will create a copy of input.png with the specified height and width. Then just make sure that the output file is inside the iconset folder.Peter Schorn– Peter Schorn2020-01-09 22:26:35 +00:00Commented Jan 9, 2020 at 22:26
This is possible using swift:
import Cocoa let iconSystemFolderPath = "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources" let iconFilePath = "\(iconSystemFolderPath)/DownloadsFolder.icns" let iconImage = NSImage(contentsOfFile: iconFilePath) let folderPath = "/Users/jmurphy/Documents/testfolder" NSWorkspace.shared.setIcon(iconImage, forFile: folderPath) You can turn it into a one liner:
swift -e 'import Cocoa; NSWorkspace.shared.setIcon(NSImage(contentsOfFile: "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/DownloadsFolder.icns"), forFile: "/Users/jmurphy/Documents/testfolder")' Tested on macOS 13.5
There is some kind of a bug (that happen in folders inside de iCloud sync) with the change of icons of "folders" nor files, at last in Catalina: When the Icon change, the UI does not refresh the folder with the new icon when it have an older one. So the second time you set an icon it not refresh all the times. Even if you do it manually with cmd+i and pasting a previously copied image as icon, the iCloud goes crazy with this.
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 ); var updateUUID = newUUID()+".txt"; terminal("echo -n > "+ sanityzeForBash(theFolder+"/Icon\r") ); terminal("rm "+ sanityzeForBash(theFolder+"/Icon\r") ); writeTextFile(theFolder+"/"+updateUUID, "_"); $.NSWorkspace.sharedWorkspace.setIconForFileOptions(img, theFolder, 0); delay(1); terminal("rm "+ sanityzeForBash(theFolder+"/"+updateUUID) ); } function writeTextFile(fileName, text) { var file = app.openForAccess(Path(fileName), { writePermission: true }) app.setEof(file, { to: 0 }); app.write( getProperties(text) +"\n\r", { to: file, startingAt: app.getEof(file) }) app.closeAccess(file) return true; } function sanityzeForBash(s) { return "'"+ s.replace("'","\\'") +"'"; } function newUUID(){ return ObjC.unwrap($.NSUUID.UUID.UUIDString); } function terminal(c) { var app = Application.currentApplication(); app.includeStandardAdditions = true; return app.doShellScript(c); } The idea of the "trick" is to create a file inside the folder before to change de icon to force the iCloud to sync, then wait 1s to delete the file.
- You need to
touchthe folder for Finder to re-render.ocodo– ocodo2020-08-26 02:51:28 +00:00Commented Aug 26, 2020 at 2:51 - I try, but it intermittent change the icon, for the first time it works all times, but not if the folder has an icon ready set. At last this is happen in Catalina.microbians– microbians2020-08-27 07:37:31 +00:00Commented Aug 27, 2020 at 7:37
- I get thinking about you say.... and found the bug, the problem is with folders that are inside the iCloud sync folders that is not happen on other folders that with touch is the only needed.microbians– microbians2020-08-27 07:45:52 +00:00Commented Aug 27, 2020 at 7:45
- Updated code → Found a fast way to update the icon when the folder is inside iCloud.microbians– microbians2020-09-02 21:39:11 +00:00Commented Sep 2, 2020 at 21:39