Command-line search with Spotlight

Command-line search with Spotlight

Spotlight can be powerful and fast, but lacks some precise control over the results. Typically you get far more results than you would ever need. The command-line interface unlocks more advanced functionality and you can also integrate it into your scripts.

The core command is “mdfind” and you could do “man mdfind” to see all the possibilties. However, here are a series of examples.

Simple

# Find every file that contains parakeet in the contents.

mdfind parakeet
# Restrict the search to a folder and ites subfolders (NOTE: Must be full path)

mdfind parakeet -onlyin /Users/admin/Pictures
# Display current matches and provide a live update when the number of matches changes. Great for testing you command but also to see live updates of things like a log file being created by your script.

mdfind parakeet -onlyin /Users/admin/Pictures -live
# Just display the live updating count. Less verbose and if you only care that it’s updating.

mdfind parakeet -onlyin /Users/admin/Pictures -live -count

Even simpler

Thereʼs an easier path that lets you type queries exactly like you would in the spotlight window, using the “-interpret” flag. This is primarily useful for scripting purposes but learning the syntax here can be useful when using the Spotlight UI as well.

# This will find only files that contain the word parakeet.

mdfind -interpret 'name:parakeet'
# Find every document containing parakeet and a date range.

mdfind -interpret 'parakeet created:>6/5/17'
# Date range search.

mdfind -interpret 'parakeet created:>6/5/17-6/9/17'
# Boolean "OR" search.

mdfind -interpret 'parakeet (created:<6/5/17 or created:>6/9/17) kind:jpeg' 
# JPEG files only.

mdfind -interpret 'eric created:>6/5/17-6/9/17 kind:jpeg'

Advanced

Files have a lot of metadata associated with them and that can be used to construct complex queries. To see the metadata associated with a file, use mdls:

mdls /Users/admin/Desktop/parakeet.py
_kMDItemOwnerUserID            = 503
kMDItemContentCreationDate = 2017-05-02 01:06:30 +0000 kMDItemContentModificationDate = 2017-06-08 22:33:36 +0000
kMDItemContentType = "public.python-script"
kMDItemContentTypeTree = (
"public.python-script",
"public.script",
"public.source-code",
"public.data",
"public.plain-text",
"public.shell-script",
"public.item",
"public.content",
"public.text",
"public.python-script"
)
kMDItemDateAdded = 2017-06-10 04:04:28 +0000
kMDItemDisplayName = "parakeet.py"
kMDItemFSContentChangeDate = 2017-06-08 22:33:36 +0000
kMDItemFSCreationDate = 2017-05-02 01:06:30 +0000
kMDItemFSCreatorCode = ""
kMDItemFSFinderFlags = 0
kMDItemFSHasCustomIcon = (null)
kMDItemFSInvisible = 0
kMDItemFSIsExtensionHidden = 0
kMDItemFSIsStationery = (null)
kMDItemFSLabel = 0
kMDItemFSName = "parakeet.py"
kMDItemFSNodeCount = (null)
kMDItemFSOwnerGroupID = 20
kMDItemFSOwnerUserID = 503
kMDItemFSSize = 16556
kMDItemFSTypeCode = ""
kMDItemKind = "Python Source"
kMDItemLogicalSize = 16556
kMDItemPhysicalSize = 20480

This gives us a lot to work with for finding similar files. Some examples:

# Find every file of a particular kind.

mdfind "kMDItemKind == 'Python Source'"
# Files created by user id 503.

mdfind "kMDItemKind == 'Python Source' && kMDItemFSOwnerUserID == 503"
# Files created in the last 10 days.

mdfind 'kMDItemKind == "Python*" && kMDItemFSOwnerUserID == 503" && kMDItemFSCreationDate > $time.today(-10)'

Super advanced

If you want to know ALL the possible metadata items, run this command:

mdimport -X

Caveat

The easiest mistakes to make are in commands that involve both single and double quotes. If you have a command that works, sometimes it’s easier to start with that and modify it as it’s easy to make mistakes. If it fails to run, look at the quotes first.