This article is part of the “Meta Advent 2019” series. I’ve committed to writing a new blog post here every day until Christmas.

macOS’s Spotlight is an extremely powerful and fast search tool. Its speed is derived from the fact that internally Spotlight relies on a pre-built file database (similar to what the Unix utility locate does). While for most people using Spotlight’s GUI interface is probably fine, people like me prefer to be able to leverage it from their terminals. Fortunately, that’s pretty easy to do, as macOS ships with a command-line interface for Spotlight called mdfind.1

Let’s play a bit with mdfind to see how it can help us. I’ll share with you some of the ways in which I normally use mdfind. I encourage all of you to try the examples locally to get a better feel for how the different commands works.

Here’s how you’d search for all files containing some text (you can think of this as some hybrid of grep and find):

$ mdfind cider

Here’s how you’d search for all files matching some name:

$ mdfind -name bozhidar.jpg

Note that this does a simple text match for the name, so you can easily expand the search by making it more generic:

$ mdfind -name bozhidar

You can also search for multiple words in the filename:

$ mdfind -name clojure mobi

You can easily limit the search to a particular directory like this:

$ mdfind -onlyin ~/Downloads -name bozhidar

Another way to limit a search is by specifying the type (kind) of the files to look for/in:

$ mdfind kind:image -name bozhidar

You can also do some fancier searches by matching for some specific macOS file metadata. The example bellow is searching for all files and folders named exactly “Clojure”:

$ mdfind "kMDItemFSName = Clojure"

Admittedly it’s not very easy to remember attribute names like this one, but the possibility this opens up are almost endless. To get an idea about the metadata attributes that exist you can check them for some file with the mdls command:

$ mdls index.md
kMDItemContentCreationDate         = 2018-10-27 06:08:22 +0000
kMDItemContentCreationDate_Ranking = 2018-10-27 00:00:00 +0000
kMDItemContentModificationDate     = 2018-10-27 06:08:22 +0000
kMDItemContentType                 = "net.daringfireball.markdown"
kMDItemContentTypeTree             = (
    "net.daringfireball.markdown",
    "public.item",
    "public.text",
    "public.data",
    "public.content",
    "net.daringfireball.markdown",
    "public.plain-text"
)
kMDItemDateAdded                   = 2018-10-27 06:08:22 +0000
kMDItemDateAdded_Ranking           = 2018-10-27 00:00:00 +0000
kMDItemDisplayName                 = "index.md"
kMDItemFSContentChangeDate         = 2018-10-27 06:08:22 +0000
kMDItemFSCreationDate              = 2018-10-27 06:08:22 +0000
kMDItemFSCreatorCode               = ""
kMDItemFSFinderFlags               = 0
kMDItemFSHasCustomIcon             = (null)
kMDItemFSInvisible                 = 0
kMDItemFSIsExtensionHidden         = 0
kMDItemFSIsStationery              = (null)
kMDItemFSLabel                     = 0
kMDItemFSName                      = "index.md"
kMDItemFSNodeCount                 = (null)
kMDItemFSOwnerGroupID              = 20
kMDItemFSOwnerUserID               = 501
kMDItemFSSize                      = 175
kMDItemFSTypeCode                  = ""
kMDItemInterestingDate_Ranking     = 2018-10-27 00:00:00 +0000
kMDItemKind                        = "Plain Text Document"
kMDItemLogicalSize                 = 175
kMDItemPhysicalSize                = 4096

You can find more information on metadata attributes, as well as some advanced mdfind queries here.

Another cool thing about mdfind is that you never have to rebuild its database manually, as this is automatically handled by macOS. When I was using GNU/Linux back in the day I’d have to setup some cron job to keep my locate database up to date, and occasionally I’d had to trigger its update manually.

That’s all I have for you today. I’d love it if you share in the comments some of your favourite uses of mdfind. See you tomorrow!

  1. I believe MD stands for “meta data”.