Understanding mdfind
By W. Clawpaws on Sunday 11 February 2007, 13:23 - Random Tips - Permalink
I love Apple's Spotlight in theory, but in practice I hate the GUI implementation. On my 1.33Mhz G4 laptop, having it try to search while I'm still trying to type the first is both painful and usually useless. And, to make matters worse, when using Spotlight from the Finder, it seems to crash the finder about 50% of the time.
So, half the time I end up just using locate or find. But I keep thinking that I should really be using mdfind. But the manual page is less than helpful. It says
The query can be a string or a query expression.
which isn't very helpful because it doesn't tell you what valid query expressions look like.
Some people tell you to just do a search in the Finder, save it as a saved
search/smart folder, and then go peek in ~/Library/Saved Searches.
There you'll find evil XML (or binary) plist files, which are unreadable by
normal people. But here's a useful trick to render them in human readable form
(i.e., the old-style ASCII plist format). If the file ends with a
.plist extension (e.g., ~/blah/foobar.plist), you can
use defaults read ~/blah/foobar (note the lack of the
.plist — the defaults command insists on adding it).
If it doesn't end with .plist, you can make a temporary
symlink that does.
So, you can look at saved searches, but learning from examples only goes so far. And, you can use mdls on existing known files to find potential attributes to use in your search.
But what you really need is to know the query expression syntax, and the metadata attributes. Why they can't just tell you about these
references on the mdfind man page I don't know.
This documentation is a good start, except that it is still fairly sparse.
From what I can tell, the inRange operator doesn't work, or at
least doesn't work on dates. This works to find the files I've changed in the
last day:
mdfind '(kMDItemFSContentChangeDate >= $time.today(-1)) && (kMDItemFSContentChangeDate < $time.now) && (kMDItemContentTypeTree = "public.content")'
but this one doesn't
mdfind '(inRange(kMDItemFSContentChangeDate,$time.today(-1),$time.now)) && (kMDItemContentTypeTree = "public.content")'
The kMDItemContentTypeTree = "public.content" part is to weed
out updated cache files and the like, although apparently
Makefiles don't qualify as content (none of the importers
recognize them, I guess), so they get weeded out too. sigh
Still, I'm closer than ever to weaning myself off locate and
find. Maybe.
Comments
Thanks for this, I was struggling with the mdfind man page and needed to know the query expression syntax.