Mac OS X: Changing the Icon for a File Type

How does OS X decide what icon to show for documents? The rules are quite complicated. Here they are for 10.4, as best as I can tell. Please note that if you’re going to change any files, you should back up the old versions first! Don’t blame me if you wreck your system. . . .

Forcing an icon on an individual file

First, you can copy/paste an icon into the Get Info box, to force a certain icon for a certain file. This overrides all the other rules. First, get an icon in your clipboard. Then go to the file you want to change and open its Info box. Click on the old icon, in the upper-left corner, and press Cmd-V. Voila! You’ve pasted the new icon. If you want to revert to the default, highlight the icon in the corner and click Delete. This does not give you a blank icon; it gives you whatever icon is the default for this type (which may still happen to be blank).

I’m not sure where Mac stores the data for these one-off icon overrides. At first I thought the .DS_Store file would be a natural place, but it appears that is not it. (Incidentally, if you want to stop Mac from adding .DS_Store files to networked drives, type this command: `defaults write com.apple.desktopservices DSDontWriteNetworkStores true`.) Perhaps the file’s icon is part of the HFS+ filesystem, hidden in the resource fork. That seems like the most Macish thing to do, but on OS X I don’t know how to confirm it. The closest I can come is running this command:

$ /Developer/Tools/GetFileInfo -ac somefile

That prints “0” if the file has a default icon, and “1” if it has a custom icon.

There are several ways to get an icon onto the Clipboard so you can paste it into a Get Info window. If you open an .icns file in Preview, make sure you can see the Drawer (Cmd-Shift-D), then if necessary click the triangle to show all the icons contained in the file. There should be several for various sizes. But no matter what icon size you use, copying from Preview and pasting into the Info box gives bad results. Weird artifacts show up in the images like static around the edges, and transparency seems to get lost. Some people report better results with GraphicConverter, although when I try copying from there, I can’t paste into Get Info at all. If you can find an icon that already has your image, open its Info box and copy from there. That yields correct results. You may also be able to open the Info window of the icon itself and copy from there, but often these files simply have the default .icns icon, so there is nothing interesting to copy.

Setting an icon for a file type

If you haven’t assigned a specific icon to a specific file, files’ icons are determined by Launch Services (LS). There is an LS database which associates file extensions with icons and applications. You can use the `lsregister` command to manage this database. This command is hidden away in a deep folder, so to run it you should use `locate lsregister`. If it bugs you to keep typing “`locate lsregister`,” you could just symlink it. This command will do the trick:

$ sudo ln -s `locate lsregister` /bin/lsregister

I think this is a nice convenience, but in this article I’ll assume you haven’t symlinked anything.

To see everything in the LS database, type:

$ `locate lsregister` -dump

You’ll probably want to redirect the output to a file or pipe it into less, like so:

$ `locate lsregister` -dump | less

You’ll see that the LS database has entries for bundles, volumes, and handlers. A bundle is more or less an application, like /Applications/TextEdit.app or /Applications/OpenOffice.org 2.4.app, but there are non-app bundles like /System/Library/CoreServices/CoreTypes.bundle and /Library/Spotlight/Microsoft Office.mdimporter. Within a bundle there may be lists of types and claims (indented). If I search my database for “.doc,” I find that CoreTypes declares a type for Microsoft Word files. Spotlight declares both a type and a claim. TextEdit declares a claim. I don’t know what a type is for, but it’s claims to matter to us here. A claim includes a role. Roles I’ve seen include “importer” (Spotlight), “viewer” (TextEdit), and “editor” (OpenOffice). A claim may also suggest an icon for the document type. In my database, no claim actually does this for .doc files, but presumably this is how you’d tell the Finder how to display files of that type.

Near the bottom of the lsregister output is a list of handlers. In my database, the handler for .doc files, for all roles, is org.openoffice.script. This happens to be the identifier for /Applications/OpenOffice.org 2.4.app! Evidently this is how your Mac knows what to use for the `open` command (aka double-clicking). To see what handlers you’ve associated with what file types, type this:

$ defaults read com.apple.LaunchServices

But back to the LS database! If you’ve owned your Mac for a while, you may see some silly entries here. For instance, I see entries for /Volumes/OpenOffice.org/OpenOffice.org 2.4.app, because I installed OO by downloading a .dmg file. I also see /Applications/OpenOffice.org 2.2.app, although I’ve deleted the 2.2 version from my system. To clean out these old entries, you can “rebuild” the database. This is a bit like “rebuilding the desktop” in pre-OS X days. Just type:

$ `locate lsregister` -kill -r -f -domain system -domain local -domain user

On OS 10.5 systems, it appears this command has changed to:

$ `locate lsregister` -kill -r -f -all system,local,user

Note that each user has his own LS database. If you run lsregister through sudo, you are changing root’s LS database, and your own will appear unaffected. Therefore you should make sure you run lsregister as yourself.

Rebuilding the database is also how you can tell your Mac to re-read applications’ Info.plist files. If you want to use particular icons for particular file types, edit an application’s Info.plist, then run lsregister. For instance, we could use this process to change the icon for .doc files. Suppose you’re cheap like me, and you have OpenOffice installed but not Microsoft Word. OpenOffice is too polite to declare an icon for .doc files, so they appear as completely blank icons. If this annoys you, you can change the Info.plist file in OpenOffice to show its icons for .doc files. I’m going to assume you’ve editted an XML file before. If not, you might want to read up about it first. If you know what you’re doing, open the .plist file and remove the line saying, “<string>doc</string>” from the long list of file extensions OpenOffice knows about. Then add a separate dictionary like this:

    <dict>
        <key>CFBundleTypeExtensions</key>
        <array>
            <string>doc</string>
        </array>
        <key>CFBundleTypeIconFile</key>
        <string>oo2-writer-doc.icns</string>
        <key>CFBundleTypeName</key>
        <string>Microsoft Word document</string>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
    </dict>

You should add this <dict> element as an immediate child of the huge <array> element—in other words, as a sibling of the many other filetype <dict> arguments you see.

I don’t know if there is some other place you can add data like this on a per-user basis. It seems unfortunate to change the application’s own .plist file. You need root privileges, your changes affect all users, and you lose your work if you ever upgrade. I guess there is probably somewhere in your home directory you could make similar changes, but I don’t know where it would be.

Finally, rebuild the LS database. Since you’ve only changed one file, you don’t need to re-read everything. You can just use a command like this:

$ `locate lsregister` -r -f /Applications/OpenOffice.org\ 2.4.app

That accomplishes the job of changing icons for a whole file type. But there are still a few more questions I’d like answered.

First, can a document ever inherit its icon from its handler’s application icon? That is, if your Mac doesn’t know what icon to use for a document, but the document has a handler, will it just use the application’s own icon? It appears to me that this never happens. A perfect example is the .doc file. OpenOffice was declared as its handler, but the icon was still blank. Unless there is some extra complexity here, it looks like document icons are completely distinct from application icons; they must be declared explicitly.

Second, what happens when two apps each declare an icon for the same file type? Having made my .doc change in OpenOffice, what if I now installed MS Word? Both OO and Word would declare an icon for .doc files, so which would I see? I think probably Mac uses whatever icon is preferred by the document’s handler. So if I went into Get Info, changed the “Open with” dropdown, and pressed the “Change All…” button, I’d see the icon declared by that application. If I opened .doc files with OO, I’d see OO’s icon. If I opened .doc files with Word, I’d see Word’s icon. If the handler declared no icon, then I think the icon would be blank, even if another application declared a non-blank icon for the same type. Most of this paragraph is just theory. I haven’t tested it, but it seems consistent with experiences I’ve read elsewhere.

Other Files

There are a few other files associated with Launch Services. I’m not sure what these two do, but they exist:

/Library/Caches/com.apple.LaunchServices-0140.csstore
/Library/Caches/com.apple.LaunchServices-014501.csstore

Apparently those numbers are associated with your user account. There is also a file here:

$HOME/Library/Preferences/com.apple.LaunchServices.plist

Although this is a .plist file, it seems to be binary. This is the file that holds the data we saw above by running `defaults read.`

Comments are closed.