Spotlight can be frustrating at times, but you can use it—as well as Smart Folders—to find a wide range of files on your Mac. Earlier this week, we ran a
hint discussing Smart Folders, and some of the comments asked how to do more with them. So this Friday hint gives you a weekend project—a chance to dig deep into Spotlight’s query language and roll your own, customized Smart Folders.
Spotlight saved searches, or “Smart Folders,” are simply XML files with a
.savedSearch extension. Within that XML file, which you can open using any text editor, there is a tag called
RawQuery; immediately following that is another called (ambiguously)
string tag right after the
RawQuery tag is the “code” for your search.
Since Spotlight limits what you can put in the query in various ways, sometimes it is hard to get what you want out of it. Boolean searches are well-documented both on this site and others—but they prove problematic and inconsistent. So this hint is intended to share some info about how to modify the “code” in the saved search to get what you want.
Let me start with a scenario. I have a bunch of images in a folder named Images, some of them with Spotlight comments Oregon , and others with the comment Mountains ; I want to find all images that are marked Mountains but not Oregon . Not so easy to do with Spotlight, at least as the interface allows. If I open a saved search for Oregon -coded pictures, I get this XML (line breaks in the
<string>… line are added for readability; there are none in the code):
<string>(* = "Oregon*"wcd || kMDItemTextContent = "Oregon*"cd) &&
(kMDItemContentType != com.apple.mail.emlx) &&
(kMDItemContentType != public.vcard)</string>
Well, that code isn’t too helpful. But Apple’s Developer documentation on
query syntax can clear up some elements. I’ll highlight the important stuff here for a simple overview.
First of all, comments in the Finder—which are called by the UI name “Spotlight Comments”—are stored in the kMDItemFinderComment key. So to search for Oregon anywhere in the comments, here is the simplest form:
<string>(kMDItemFinderComment == "*oregon*"cd )</string>
The operators are:
!= not equal
< less than
> greater than
<= less than or equal to
>= greater than or equal to
* is the wildcard: Placed at the beginning, like
*oregon, gets anything that ends with oregon. Placed at the end, like
oregon*, will get anything that starts with oregon. Placed on both sides, like
*oregon* will return anything with oregon anywhere.
And then there is that strange
cd there at the end (
… == “*oregon*”cd ) which looks like a typo. That is not a typo, but rather it specifies how the comparison is to be made:
w makes the comparison based on whole words
c makes the comparison not case sensitive (ignore case)
d makes the comparison diacritical insensitive. (That means that it ignores accented characters).
So to find anything that contains Mountain but not Oregon , the query would look like this:
<string>(kMDItemFinderComment == "*mountain*"cd &&
kMDItemFinderComment != "*oregon*"cd )</string>
Again, the line break in the
<string>… line was added for legibility; remove it when entering the text in the file.
This one example should show you how you can easily edit saved searches, that is, smart folders, to make them do more of what you want. This was just a small example—try some on your own and see what you can do.