16

I'm trying to figure out how to perform wildcard searches for filenames with mdfind on OsX? I tried: mdfind -name "*.pdf" but it didn't work.

EDIT: I want to be able to find names like "test*.pdf"

5
  • 2
    mdfind is such a pain to use! As an alternative, locate comes preinstalled, so if you sync the index (with sudo /usr/libexec/locate.updatedb), you can use it instead, and avoid learning the mdfind syntax. Of course, the huge disadvantage is that you would need to sync manually. See also developer.apple.com/library/mac/documentation/Darwin/Reference/… NB: Just to clarify: locate is not using Spotlight, but for Linux users would probably be more familiar.
    – ccpizza
    Commented Dec 11, 2014 at 13:50
  • Below is a pseudo locate that uses mdfind you can add to your bash initialization. function mdname () { if [ $1 = "-i" ]; then shift mdfind "kMDItemDisplayName == '$@'c" else mdfind "kMDItemDisplayName == $@" fi } - the best of both worlds though messed up by the inability to add formatted code to comments so you'd need to add ;'s or new lines as in the original where those big gaps are.
    – jwd630
    Commented Jan 14, 2015 at 23:05
  • @ccpizza Sadly the locate that ships with macOS runs as nobody, and can't search folders for which that user has no permissions to. You can use homebrew to install GNU Locate, apparently. See: stackoverflow.com/questions/15887431/… Commented Mar 21, 2018 at 19:57
  • can you just use 'ls *.pdf' from some sufficient directory? the options on ls before filenames will determine your output.
    – Natsfan
    Commented May 2, 2018 at 3:40
  • Note that locate does not update its database with every filesystem change like spotlight/mdfind does. It's typically updated once per week, I believe, so it might not be appropriate for some more immediate tasks. Commented May 13, 2020 at 13:54

4 Answers 4

25

This should work:

mdfind "kMDItemDisplayName == test*.pdf"

Enclose the pattern in single quotes and add 'c' to match case-insensitively:

mdfind "kMDItemDisplayName == 'test*.pdf'c"

Here is a list of available attributes. You can combine multiple attribute/value pairs with &&.

3
  • I could only get mdfind to work when the wildcard was at the start or end of the name. So instead of test*.pdf, I had kludge it to mdfind "kMDItemDisplayName == 'test*' | grep pdf. (Even better, pipe to grep \\.pdf$.) Sigh. Commented Mar 21, 2018 at 19:53
  • Oops, a missing double-quote in my preceding comment; for copypastability: mdfind "kMDItemDisplayName == 'test*'" | grep pdf. Commented Mar 21, 2018 at 20:17
  • FWIW the * inside the name worked fine for me
    – dgrogan
    Commented May 15, 2019 at 0:14
7

macOS ships with the regular find command, and mdfind is not a replacement for find.

If you really just want to search the current directory for all pdf files, you should probably just do find . -name '*.pdf'

By default mdfind searches by file content and metadata, and it searches your entire hard drive instead of just a single directory — on my system mdfind pdf finds tens of thousands of results.

If you must use mdfind, because it's faster, you have a few options to limit the results, for example:

mdfind pdf -onlyin .
mdfind 'kMDItemFSName = *.pdf' -onlyin .
mdfind 'kMDItemContentTypeTree = *.pdf' -onlyin .

Use mdls to learn what metadata is available for a file, and the syntax for pattern matching is very minimalist since it needs to match the database index of your filesystem.

Alternatively you can mdfind with grep, giving the speed of mdfind and full regex matching on the file path. For example:

mdfind pdf -onlyin . | grep 'pdf$'

One final caveat is mdfind does not search your actual file system, it only searches the spotlight database which may be missing parts of the filesystem or inaccurate. Use find if you require reliable results. Use mdfind when you require speed over accuracy and when you need complicated search terms (eg find all pdf files that were created within a specific date range and contain a phrase of text).

4

When explicitly searching for filenames, my experience is that the kMDItemFSName attribute provides more concise results. Another suggestion: add the d comparison modifier (insensitive to diacritical marks) to e.g. match a file called "Entrée Menu.pdf" when searching for "entree":

mdfind 'kMDItemFSName == "*entree*"cd'

Also, since @tcmb's link to the attributes reference is dead, here are two working ones: Spotlight Metadata Attributes and iCloud Metadata Attributes.

0

If you find yourself frequently wanting to use Spotlight to search for filenames by glob patterns, it might be worth it to wrap it into a script by saving this code into a mdfindfile on your path:

#!/usr/bin/env bash
# case-insensitive search for $1, maybe in dir $2
case "$#" in
    0) echo "usage: $(basename $0) PATTERN [DIR]"
       echo ""
       echo "  Lists paths of files matching PATTERN in DIR or below"
       ;;
    1) exec mdfind "kMDItemDisplayName == '$1'c"
       ;;
    *) exec mdfind "kMDItemDisplayName == '$1'c" -onlyin "$2"
       ;;
esac

Then you can just do mdfindfile "*.pdf" to search your machine or mdfindfile "*.pdf" ~/Documents to search below your Documents, or whatever.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .