Creating a ZIP with a Folder-Icon for OS X
Posted on
A few days ago I wanted to send a ZIP to a customer and I wanted the root-folder to have an icon, so it’s visually distinguishable as a “special” folder in the user’s home-directory.
However, zipping a folder with a set icon and then extracting it somewhere else doesn’t restore the icon properly. Here’s one way to fix this.
OS X saves icons in a resource fork and extended attributes. See this KB-entry on setting an icon for a folder.
After you’ve set an icon, the folder will look like that:
seb@zhuk:~/Folder$ ls -al@
total 3912
drwxr-xr-x@ 2 seb staff 102 12 Jun 13:51 .
com.apple.FinderInfo 32
drwxr-xr-x+ 68 seb staff 3978 12 Jun 13:51 ..
-rw-r--r--@ 1 seb staff 0 12 Jun 13:51 Icon?
com.apple.FinderInfo 32
com.apple.ResourceFork 40625
As you can see, the icon is saved in a resource fork, there’s a special file Icon\r
and there are extended attributes on that file and on “.”.
Rather complicated, but that’s how it is.
First, we need to ZIP it in a way that resource forks and extended attributes are preserved. Command line ZIP and e.g. Archiver don’t do that, but OS X’s Archive Utility does. In 10.7, it doesn’t shop up in Applications and is not indexed by Spotlight, so start it by calling
open /System/Library/CoreServices/Archive\ Utility.app/
In later versions (tested on 10.11) it can be found with Spotlight.
Then, configure it to create ZIP-files and zip the folder with the icon.
If you decompress this folder somewhere else, you’ll see that there’s no icon displayed by Finder.
If you do a ls -al@
on the decompressed folder you’ll find that the extended attribute com.apple.FinderInfo
is missing on the top-level directory.
I don’t know why Archive Utility doesn’t zip it. I don’t think it’s for security reasons, as it happily extracts it if it’s present, as we’ll see later.
If we list the contents with command-line-ZIP, it will look like that:
seb@zhuk:~$ zip -Tv Folder.zip
Archive: Folder.zip
testing: Folder/ OK
testing: Folder/Icon^M OK
testing: __MACOSX/ OK
testing: __MACOSX/Folder/ OK
testing: __MACOSX/Folder/._Icon^M OK
No errors detected in compressed data of Folder.zip.
test of Folder.zip OK
So, resource forks and extended attributes are saved to a __MACOSX
-folder, as every Windows-user knows if they’ve ever extracted ZIPs from a Mac.
If there’s a subdirectory with an icon, Archive Utility happily saves everything and the icon will show after extraction.
That’s how I found out what’s missing to make sure the extended attribute com.apple.FinderInfo
will also be put in place for the top-level-directory.
What is needed in this case is a file called __MACOSX/._Folder
with contents that restore the com.apple.FinderInfo
-attribute.
It’s a file with 82 bytes in size.
With this small Python-script I’ve called osx-iconize-zip-folder.py
it can be done:
#!/usr/bin/env python
import zipfile, sys
finderInfoXattr = [
0, 5, 22, 7, 0, 2, 0, 0, 77, 97, 99, 32, 79, 83, 32, 88,
32, 32, 32, 32, 32, 32, 32, 32, 0, 2, 0, 0, 0, 9, 0, 0,
0, 50, 0, 0, 0, 32, 0, 0, 0, 2, 0, 0, 0, 82, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0
]
z = zipfile.ZipFile( sys.argv[1], "a" )
rootName = z.namelist()[0].strip( "/" )
destFile = "__MACOSX/._" + rootName
print "Root directory is '" + rootName + "'"
print "Putting com.apple.FinderInfo data to '" + destFile + "'"
z.writestr( destFile, str( bytearray( finderInfoXattr ) ) );
Then, we can do this:
seb@zhuk:~$ ./osx-iconize-zip-folder.py Folder.zip
Root directory is 'Folder'
Putting com.apple.FinderInfo data to '__MACOSX/._Folder'
seb@zhuk:~$ zip -Tv Folder.zip
Archive: Folder.zip
testing: Folder/ OK
testing: Folder/Icon^M OK
testing: __MACOSX/ OK
testing: __MACOSX/Folder/ OK
testing: __MACOSX/Folder/._Icon^M OK
testing: __MACOSX/._Folder OK
No errors detected in compressed data of Folder.zip.
test of Folder.zip OK
Extract the resulting Folder.zip somewhere and the folder will have an icon, hurra!
The above was done on OS X 10.7, but it’s probably the same for newer versions. The Python that comes with it is version 2.7.1.