Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get mdfind to include folder matches in addition to files?

In terminal I am using mdfind 'kMDItemFSLabel = 6' to find everything with a Red file label on my Mac. However, it seems to be excluding folders with a red label. I'm trying to get it turn also return folders but I can't seem to even get any of these folder-only queries to work let alone add it to the current file results. mdfind kind:folders and mdfind 'kMDItemFSLabel=6' work independently but I can't figure out how to get both:

mdfind kind:folders AND 'kMDItemFSLabel == 6'
mdfind 'kind:folders' AND 'kMDItemFSLabel == 6'
mdfind 'kind:folders kMDItemFSLabel == 6'
mdfind kind:folders kMDItemFSLabel == 6
etc

All I get is Failed to create query for [query above]

What is the correct syntax?

And once I get that right, how do I say "folders AND all files"? Something like `kind:folders+all'?

Edit: Also tried:

mdfind kind:folders && 'kMDItemFSLabel == 6'   returns every folder on my computer
mdfind kind:folders && kMDItemFSLabel == 6   returns every folder on my computer
mdfind 'kind:folders' && 'kMDItemFSLabel == 6' returns every folder on my computer
mdfind 'kind:folders && kMDItemFSLabel == 6'   failed to create query
like image 623
truth1ness Avatar asked May 16 '15 02:05

truth1ness


2 Answers

tl; dr

Use the following, locale-independent commands:

  • files and folders:
    • mdfind 'kMDItemUserTags == Red'
  • files only:
    • mdfind 'kMDItemUserTags == Red && ! kMDItemContentType == public.folder'
  • folders only:
    • mdfind 'kMDItemUserTags == Red && kMDItemContentType == public.folder'

Simpler, but locale-specific equivalents - these examples only work in English-language locales and must be localized to work with other locales:

  • files and folders:
    • mdfind 'tag:red'
  • files only:
    • mdfind 'tag:red AND NOT kind:folder'
  • folders only:
    • mdfind 'tag:red AND kind:folder'

For background information, read on.


As it turns out, Spotlight - and therefore mdfind - speak two distinct languages:

  • SL - Simple language: A simplified, LOCALIZED language based on <attribName>:<attribVal pairs
    • based on simplified, localized attribute names comprising only a subset of all attributes (however, alternatively, you can also use the full, locale-independent attribute names)
      • some attribute values are localized as well; e.g., attribute kind(kMDItemKind) is explicitly designed to report a localized value
    • based on simplified matching rules
    • combined with Boolean operators AND (default), OR, and NOT (note that these do not get localized).
  • FL - Flexible language: A more powerful and locale-independent, but more complex and verbose language
    • based on the locale-independent underlying attribute names
    • using a range of relational operators
    • with more flexible value-matching options
    • combined with Boolean operators && (default), ||, and !

If anyone knows what to properly call these two languages, please let me know.

Caveat: These two languages cannot be mixed - a given query string must use either one or the other syntax.

The solutions below are tagged with SL and FL accordingly. Given that SL uses localized names, I recommend using the SL solutions for predictable, locale-independent results, despite being more complex and verbose.


To find all files and folders that are tagged with the red label, use:

  • FL:

      mdfind 'kMDItemUserTags == Red'
    
  • SL (English):

      mdfind 'tag:red' # in German, `tag:red` would be `attribut:red`
    

To find files only (as opposed to folders) that are tagged with the red file/folder label, use:

  • FL:

      mdfind 'kMDItemUserTags == Red && ! kMDItemContentType == public.folder'
    
  • SL (English):

      mdfind 'tag:red AND NOT kind:folder' # in German, `kind:folder` would be `art:ordner`
    

To find folders only (as opposed to files) that are tagged with the red file/folder label, use:

  • FL:

      mdfind 'kMDItemUserTags == Red && kMDItemContentType == public.folder'
    
  • SL (English):

      mdfind 'tag:red AND kind:folder'
    

General tips for using mdfind:

  • Pass the query as one, single-quoted string, so as to protect it from interpretation by the shell (as above).
  • If you're unsure how to formulate a query:
    • Create the desired query interactively via Finder's search field (start typing and select query fields from the pop-up list, or press + in the top-right corner for creating multiple, AND-combined criteria line by line with the assistance of pop-up lists)
    • save it to a *.savedSearch file (Save button in the top-right corner, which saves to ~/Library/Saved Searches/ by default),
    • and open an Inspector window for that file and look at the Query: field.
    • Note that such system-created queries always use the FL language.
  • To see a list of all supported metadata attributes and their description, examine the output from mdimport -A.
    • Column 1 contains the FL attribute names.
    • Column 4 contains the SL attribute names (simplified, localized).
  • To restrict matches to a specific folder's subtree, use the -onlyin <folder> option.
  • To output the value of specific metadata attributes after the path of matches, use one or more -attr <attribName> options.

Documentation:

Note: The documentation is woefully lacking and, in parts, incorrect.as of 16 May 2015

  • About File Metadata Queries
  • Query expression syntax - FL ONLY
    • Caveat: the c and d options are explained as needing to be appended to the operator as [c] and [d], as opposed to the (right-hand-side) operand, which is what OSX itself does when you save interactively constructed queries; also, at least on other option exits that's not even mentioned: w; if you append one or more option letters to a quoted string, their meaning is as follows
    • c ... match case-INsensitively
    • d ... ignore diacritics (marks above and below the base letter of foreign characters) when matching
    • w ... match as a whole word (from what I can tell)
    • You can also use the familiar * (any sequence of chars.) and ? (one char.) wildcards.
  • List of common Metadata Attributes - FL ONLY
    • Note that since Spotlight is extensible with plugins, any given machine may have additional attributes; to see the file-type-to-attributes mappings, run mdimport -X and look at the entries of the Types key.

All in all, as of macOS 10.10.3, mdfind and the Spotlight query language are poorly documented, finicky beasts - trial and error are often your best friends, sadly.

like image 165
mklement0 Avatar answered Oct 03 '22 09:10

mklement0


The following seems to work:

mdfind 'kMDItemContentType = "public.folder" && kMDItemUserTags = "Red"cd'

By the way, the cd on the end of "Red" means the match should ignore case (upper vs. lower) and diacritical marks (accents, etc.).

like image 29
Ken Thomases Avatar answered Oct 03 '22 10:10

Ken Thomases