* Finder labels look like tags in the Finder, but they are stored differently in Spotlight metadata.
* The Spotlight metadata of files created before tags existed retain their entries for Finder label, but obviously have no reference to tags. Files labeled via Finder scripting even under the current OS also have their labels stored only as Finder labels, not tags. (Yet another strike against finder's scripting implementation.)
* Files tagged with one of the default tags have the tag added to their Spotlight metadata, and they also have the Finder label value in their Spotlight metadata set to the label that was equivalent to that color. If you tag them with another default tag, the Finder label value will be updated to the new value.
* When you search using either mdfind, the tags command-line tool's --find option, or the script I posted earlier, only tags are searched, not Finder labels.
* When you search in a Finder window for files with a default tag, the search will find all files with that tag *as well as* all files with the equivalent Finder label.
* If you want to do a similar search via script, you need to search for both matching tags and Finder labels via mdfind, or use the script below.
* If you use the script below or a compound mdfind search, there will still be minor differences. (Folders with labels and no tags seem to be skipped, and some items, such as taged script libraries, are found by the script but not in the Finder). It looks like they might be using different search APIs (NSMetadataQuery vs MDQuery).
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property searchIsDone : false -- search flag
my searchInListOfPaths:{(current application's NSMetadataQueryUserHomeScope)} forTags:{"Red"}
on searchInListOfPaths:scopeList forTags:tagList -- pass empty list for any tags
(* scope can be a list of POSIX paths and/or the following enums:
NSMetadataQueryUserHomeScope
NSMetadataQueryLocalComputerScope
NSMetadataQueryNetworkScope
NSMetadataQueryUbiquitousDocumentsScope
NSMetadataQueryUbiquitousDataScope
NSMetadataQueryAccessibleUbiquitousExternalDocumentsScope
NSMetadataQueryIndexedLocalComputerScope -- 10.10 or later
NSMetadataQueryIndexedNetworkScope
Eg:
searchInListOfPaths:{current application's NSMetadataQueryLocalComputerScope} forTags:tagList
*)
-- Build the search predicate
set tagListCount to count of tagList
if tagListCount = 0 then -- any tag or Finder label
set pred to current application's NSPredicate's predicateWithFormat:("(kMDItemUserTags LIKE '*') OR (kMDItemFSLabel LIKE '*')")
else if tagListCount = 1 then
-- get list of old Finder label names
set theWS to current application's NSWorkspace's sharedWorkspace()
set theLabels to theWS's fileLabels()
-- check if tag name is also a Finder label name, and if so also look for that
set theIndex to theLabels's indexOfObject:(item 1 of tagList)
if theIndex < 8 then
set pred to current application's NSPredicate's predicateWithFormat:"(kMDItemFSLabel == %@) OR (kMDItemUserTags CONTAINS[c] %@)" argumentArray:{theIndex, item 1 of tagList}
else -- not a label name
set pred to current application's NSPredicate's predicateWithFormat:"kMDItemUserTags CONTAINS[c] %@" argumentArray:tagList
end if
else
-- get list of old Finder label names
set theWS to current application's NSWorkspace's sharedWorkspace()
set theLabels to theWS's fileLabels()
-- build list of predicates
set predList to {}
repeat with aTag in tagList
set end of predList to (current application's NSPredicate's predicateWithFormat:"kMDItemUserTags CONTAINS[c] %@" argumentArray:{aTag})
-- check if tag name is also a Finder label anme, and if so also look for that
set theIndex to (theLabels's indexOfObject:aTag)
if theIndex < 8 then
set end of predList to (current application's NSPredicate's predicateWithFormat:"kMDItemFSLabel == %@" argumentArray:{theIndex})
end if
end repeat
set pred to current application's NSCompoundPredicate's orPredicateWithSubpredicates:predList
end if
-- make the query
set theQuery to current application's NSMetadataQuery's alloc()'s init()
theQuery's setPredicate:pred
-- set its scope
theQuery's setSearchScopes:scopeList
-- tell the notification center to tell us when it's done
set notifCenter to current application's NSNotificationCenter's defaultCenter()
notifCenter's addObserver:me selector:"searchDone:" |name|:(current application's NSMetadataQueryDidFinishGatheringNotification) object:theQuery
-- start searching
set my searchIsDone to false
theQuery's startQuery()
-- loop until it's done
repeat
delay 0.01
if searchIsDone then exit repeat
end repeat
-- get results
set theCount to theQuery's resultCount()
set resultsArray to current application's NSMutableArray's array() -- to hold results
repeat with i from 1 to theCount
-- (resultsArray's addObject:((theQuery's resultAtIndex:(i - 1))'s valuesForAttributes:{current application's NSMetadataItemPathKey, "kMDItemUserTags"})) -- if you want tags too
(resultsArray's addObject:((theQuery's resultAtIndex:(i - 1))'s valueForAttribute:(current application's NSMetadataItemPathKey))) -- paths only
end repeat
return resultsArray as list
end searchInListOfPaths:forTags:
on searchDone:notification
set theQuery to notification's object()
-- stop query, cancel notifications
theQuery's stopQuery()
set notifCenter to current application's NSNotificationCenter's defaultCenter()
notifCenter's removeObserver:me |name|:(current application's NSMetadataQueryDidFinishGatheringNotification) object:theQuery
set my searchIsDone to true
end searchDone: