Skip to content

Instantly share code, notes, and snippets.

@cwalston
Last active January 19, 2021 01:12
Show Gist options
  • Save cwalston/7368493 to your computer and use it in GitHub Desktop.
Save cwalston/7368493 to your computer and use it in GitHub Desktop.
SEARCHING ON OS X VIA SPOTLIGHT METADATA INDEX, & MANAGING INDEXING FROM FACTOR
! (C) 2013 Charles Alston.
USING: accessors arrays byte-arrays fry google.search io
io.encodings.utf8 io.launcher kernel locals make namespaces
sequences simple-tokenizer splitting strings unicode.categories
webbrowser wordtimer ;
IN: spotlight
! *** SEARCHING ON OS X VIA SPOTLIGHT METADATA INDEX, & MANAGING INDEXING FROM FACTOR ***
! *** MAC OS X 10.6.8 & LATER: IMPLEMENTING mdfind, mdls, mdutil, mdimport ***
! mdfind, mdls, mdutil, mdimport TAKE A QUERY ON THE STACK & RETURN A SEQUENCE OF RESULT STRINGS
! -----
! TO DO:
! -HANDLE CASE-SENSITIVITY PROPERLY (OS X)
! -DETERMINE WHICH STRING CONSTANTS ARE REALLY USEFUL
! -TEST COMPOSING VARIANT SHELL COMMAND CONSTRUCTIONS,
! E.G., THOSE WHICH DO OR DON'T NEED SPACES. PARENS, SINGLE QUOTES, ETC.-
! (WORK THROUGH EXAMPLES AT END OF FILE)
! -ACCESS O.E.D & CALCULATOR THROUGH SPOTLIGHT
! -EMIT SOME SORT OF 'NOT-FOUND' MSG FOR UNSUCCESSFUL SEARCH
! -TRAP ERRORS
! ...
! -----
! ONLY BECAUSE DEFINITION MESSED WITH TEXTMATE FORMATTING; SEE AT END OF DEFINITIONS BELOW
DEFER: double-quote
! : double-quote ( -- string ) \ " name>> ;
! FOR BUILDING COMMAND STRINGS (PROBABLY DON'T NEED MOST OF THESE)
CONSTANT: OR "|"
CONSTANT: NOT "-"
CONSTANT: == "=="
CONSTANT: != "!=" ! “not equal”
CONSTANT: less-than "<"
CONSTANT: more-than ">"
ALIAS: to-file more-than
CONSTANT: less|equal "<="
CONSTANT: more|equal ">="
CONSTANT: onlyin "-onlyin"
CONSTANT: null "-0"
CONSTANT: lit "-literal"
CONSTANT: interpret "-interpret"
CONSTANT: default-search-path "/"
CONSTANT: single-quote "'"
CONSTANT: query-blank " "
CONSTANT: double-amp "&&"
CONSTANT: triple-amp "&&&"
CONSTANT: kind "kind:"
CONSTANT: date "date:"
CONSTANT: $time "$time."
CONSTANT: today "today"
CONSTANT: yesterday "yesterday"
CONSTANT: tomorrow "tomorrow"
CONSTANT: this_week "this_week"
CONSTANT: this_month "this_month"
CONSTANT: this_year "this_year"
CONSTANT: next_month "next_month"
CONSTANT: next_week "next_week"
CONSTANT: next_year "next_year"
CONSTANT: left-paren "("
CONSTANT: right-paren ")"
! PRODUCES THE STRING " && "
: <bl&&bl> ( -- string ) query-blank double-amp append query-blank append ;
! -----
! E.G., "com.microsoft.word.doc" ContentType (query-by-attribute) BUILDS:
! "'kMDItemContentType == \"com.microsoft.word.doc\"'"
:: (query-by-attribute) ( item-name attr-name -- string )
[ attr-name % query-blank % == % query-blank %
single-quote % item-name % single-quote % ] "" make ;
: query-prefix ( -- string ) "mdfind -onlyin / \"" ;
! RESTRICT THE SEARCH PATH
:: new-search-prefix ( my-search-path -- string )
query-prefix "/" my-search-path replace ;
: query-suffix ( -- string ) "\"" ;
! EXAMPLES:
! "com.microsoft.word.doc" ContentType query-by-attribute mdfind
! "Dylan" Composer by-attribute mdfind
:: query-by-attribute ( item-name attr-name -- command-string )
query-prefix item-name attr-name (query-by-attribute) append query-suffix append ;
ALIAS: by-attribute query-by-attribute
! -----
:: (by-attribute+parms) ( cmd-vector parms attr-name -- string )
cmd-vector attr-name suffix! parms tokenize "" glue ;
! E.G., "date:yesterday" "pdf" with-parms mdfind
! Return all files on disk (/) that have been modified in the last 3 days:
! TO EMULATE:
! $ mdfind -onlyin / 'kMDItemFSContentChangeDate >= $time.today (-3)'
! COMPOSE:
! { "mdfind" "-onlyin" "/" "kMDItemFSContentChangeDate" ">=" "$time.today" "(-3)" }
! E.G., ">= $time.today (-3)" FSContentChangeDate with-parms mdfind
! ( string1 string2 -- string3 )
:: by-attribute+parms ( parms attr-name -- string )
query-prefix but-last tokenize ! ( -- vector )
parms attr-name (by-attribute+parms) ;
ALIAS: with-parms by-attribute+parms
! -----
! WITHOUT SPACES IN FILENAME,E.G., "README.md" by-filename mdfind
:: by-filename ( f-name -- string )
query-prefix but-last f-name "-name " prepend append ;
! -----
! E.G., "month-name check-month" by-phrase mdfind
:: by-phrase ( pstring -- string )
query-prefix
"""'"phrase-stub"'""" "phrase-stub" pstring replace append
query-suffix append
;
! -----
! E.G., FOR 2 TERMS IN A DOCUMENT: "Document cocoa.messages selector" by-kind mdfind
! OR, FOR ALL DOCUMENTS: "Document" by-kind mdfind - (WHOA! - LONG WAIT IF THERE ARE LOTS).
:: by-kind ( mykind -- string ) query-prefix mykind kind prepend append query-suffix append ;
! *********************** mdfind ***********************
! EXAMPLE QUERIES:
! *** Return all files that have been modified today:
!
! *** FILENAME WITH SPACES, E.G., "Finding Joy in Combinators.pdf" by-FSName mdfind
! *** FILENAME WITHOUT SPACES , E.G., "libfactor.dylib" by-filename mdfind
! *** PHRASE WITH SPACES, E.G., "Building Factor from source" by-phrase mdfind
! *** PHRASE OR TERM WITHOUT SPACES, E.G., "call-effect-unsafe" by-phrase mdfind
! OR, E.G, "metadata" by-phrase mdfind
! *** OTHERS, AS PER MetaData ATTRIBUTE (SEE BELOW), E.G.,
! "com.microsoft.word.doc" ContentType by-attribute mdfind
! ONCE A COMMAND IS BUILT, THIS DOES THE WORK
: utf8-stream-lines ( command -- seq ) utf8 [ lines ] with-process-reader ;
! : mdfind ( query -- seq ) utf8 [ lines ] with-process-reader ;
ALIAS: mdfind utf8-stream-lines
! *********************** mdls ***********************
! *** Getting Uniform Type Identifiers and Other Metadata of a Given File ***
: >mdls-command ( absfilepath -- string ) ! TO DO: LOG ERRORS
'[ "mdls " % double-quote % _ % double-quote % ] "" make ! ( -- string )
;
! EXAMPLE:
! "/Users/cwalston/factor/basis/ascii/ascii.factor" mdls
: mdls ( absfilepath -- seq )
>mdls-command utf8-stream-lines ;
! *********************** mdutil ***********************
! *** Re-indexing Spotlight ***
! ➜ ~ git:(master) ✗ mdutil
! Usage: mdutil -pEsa -i (on|off) volume ...
! Utility to manage Spotlight indexes.
! -p Publish metadata.
! -i (on|off) Turn indexing on or off.
! -E Erase and rebuild index.
! -s Print indexing status.
! -a Apply command to all volumes.
! -v Display verbose information.
! NOTE: Run as owner for network homes, otherwise run as root.
! ➜ ~ git:(master) ✗
CONSTANT: publish "-p"
CONSTANT: on "-i on"
CONSTANT: off "-i off"
CONSTANT: e/r "-E"
CONSTANT: status "-s"
CONSTANT: all-vols "-a"
CONSTANT: verbose "-v"
CONSTANT: as-root "sudo mdutil " ! run as root
CONSTANT: as-owner "mdutil " ! Run as owner for network volumes
! "sudo mdutil -E /
! This will re-index every mounted volume on the Mac, including hard
! drives, disk images, external drives, etc. Specific drives can be chosen
! by pointing to them in /Volumes/, to only rebuild the primary Macintosh HD:
! sudo mdutil -E /Volumes/Macintosh\ HD/
! To re-index an external drive named “External” the command would be:
! sudo mdutil -E /Volumes/External/
! Use of the mdutil command will spin up mds and mdworker
! processes as Spotlight goes to work."
! EXAMPLE:
! "/Volumes/Jurassic Grad - Spare Change" md-re-index
! RETURNED: ( -- { "/Volumes/Jurassic Grad - Spare Change:" "\tIndexing enabled. " } )
! *** N.B. - THIS STARTS INDEXING AS INTENDED, BUT SPOTLIGHT OFTEN HAS THE IRRITATING HABIT
! OF INDEXING 'TIL THE COWS COME HOME! I SUCCEEDED IN SPANKING THAT BEHAVIOR TO A HALT
! BY QUITTING THE mds SYSTEM PROCESS IN Activity Monitor.
! TIP: GOOGLE "Spotless", A WELL-RECOMMENDED SHAREWARE APP THAT KNOWS HOW TO MANAGE THE BEAST.
: escape-spaces? ( string -- string' )
dup " " swap subseq? [ " " split [ >byte-array BV{ } clone-like CHAR: \ suffix! >string ] map
" " join but-last >byte-array BV{ } clone-like >string ] when
;
: escape-path? ( path -- path' ) escape-spaces? ! ( -- string )
dup last CHAR: / = not [ >byte-array BV{ } clone-like CHAR: / suffix! >string ] when
;
! E.G., BUILD:
! sudo mdutil -E-s /Volumes/Jurassic\ Grad\ -\ Spare\ Change/
! ?? HOW TO INTERCEPT THE AUTHENTICATION PROMPT FROM sudo ????
: md-re-index ( abspath -- seq )
escape-path? ! ( -- string )
'[ as-root % "-E" % "-s" % " " %
_ % ] "" make utf8-stream-lines ;
ALIAS: mdutil md-re-index
! *********************** mdimport ***********************
! *** Individually Re-indexing Selected Files ***
! ➜ ~ git:(master) ✗ mdimport
! Usage: mdimport [OPTION] path
! -d debugLevel Integer between 1-4
! -g plugin Import files using the listed plugin, rather than the system installed plugins.
! -p Print out performance information gathered during the run
! -A Print out the list of all of the attributes and exit
! -X Print out the schema file and exit
! -L Print out the List of plugins that we are going to use and exit
! -r Ask the server to reimport files for UTIs claimed by the listed plugin.
! -n Don't send the imported attributes to the data store.
! ➜ ~ git:(master) ✗
CONSTANT: debugLevel "-d "
CONSTANT: use-plugin "-g "
CONSTANT: info "-p"
CONSTANT: attributes "-A"
CONSTANT: schema "-X"
CONSTANT: plugins "-L"
CONSTANT: reimport "-r"
CONSTANT: no-attr "-n"
! "In rare cases, Spotlight can miss a file during index, so rather than
! re-index an entire drive you can also manually add an individual file to
! the search index with the mdimport command:
! mdimport /path/to/file
! The mdimport command can be used on directories as well."
! A SIMPLE, NO OPTIONS EXAMPLE - TOUCH FILE & RETRIEVE ITS MetaData:
! "/Users/cwalston/factor/mdimport-test" [ touch-file ] keep [ mdimport ] keep mdls
! OR JUST:
! "/Users/cwalston/factor/mdimport-test" mdimport
: mdimport ( abspath -- seq )
'[ "mdimport" % query-blank % info % query-blank % _ % ] "" make
utf8-stream-lines
;
! ************************** METADATA ATTRIBUTES *****************************
! FROM MAC HEADER FILE: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Headers/MDItem.h
! AND FROM *CoreFoundation/CoreFoundation.h, *Metadata/MDItem.h, *Metadata/MDQuery.h, *Metadata/MDSchema.h, *Metadata/MDImporter.h
CONSTANT: Comment "kMDItemComment"
! This is a comment related to a file, and can be any random
! string. Type is a CFString
: by-Comment ( query-spec -- string ) Comment query-by-attribute ;
CONSTANT: Copyright "kMDItemCopyright"
! This is the copyright of the content. Type is a CFString
: by-Copyright ( query-spec -- string ) Copyright query-by-attribute ;
CONSTANT: WhereFroms "kMDItemWhereFroms"
! This attribute indicates where the item was obtained from.
! Examples:
! - downloaded file may refer to the site they were downloaded from,
! the refering URL, etc
! - files reveived by email may indicate who sent the file, the
! message subject, etc
! Type is a CFArray of CFStrings
: by-WhereFroms ( query-spec -- string ) WhereFroms query-by-attribute ;
CONSTANT: LastUsedDate "kMDItemLastUsedDate"
! This is the date that the file was last used, this field is updated
! by LaunchServices everytime a file is opend by double clicking or
! by asking LaunchServices to open a file. Type is a CFDate
: by-LastUsedDate ( query-spec -- string ) LastUsedDate query-by-attribute ;
CONSTANT: ContentCreationDate "kMDItemContentCreationDate"
! This is the date that the contents of the file were created,
! has an application specific semantic.
! Type is a CFDate.
: by-ContentCreationDate ( query-spec -- string ) ContentCreationDate query-by-attribute ;
CONSTANT: ContentModificationDate "kMDItemContentModificationDate"
! This is the date that the contents of the file were last
! modified, has an application specific semantic. For example an
! application can use this field to mark when the file was last
! modified, this date is not related to the file system modification
! date, but can be independent of that. This allows tracking of the
! last time the content was modified irrespective of the last time the
! file was modified. Type is a CFDate.
: by-ContentModificationDate ( query-spec -- string )
ContentModificationDate query-by-attribute ;
CONSTANT: DurationSeconds "kMDItemDurationSeconds"
! This is the duration, in seconds, of the content of the file (if
! appropriate). A value of 10.5 represents media whose content is
! 10 and 1/2 seconds long. Type is a CFNumber.
: by-DurationSeconds ( query-spec -- string ) DurationSeconds query-by-attribute ;
CONSTANT: ContactKeywords "kMDItemContactKeywords"
! A list of contacts that are somehow associated with this document,
! beyond what is captured as Author.
: by-ContactKeywords ( query-spec -- string ) ContactKeywords query-by-attribute ;
CONSTANT: Version "kMDItemVersion"
! A version number for this item. Type is a CFString
: by-Version ( query-spec -- string ) Version query-by-attribute ;
CONSTANT: PixelHeight "kMDItemPixelHeight"
! The height of the document in pixels (ie Image height or Video frame height)
: by-PixelHeight ( query-spec -- string ) PixelHeight query-by-attribute ;
CONSTANT: PixelWidth "kMDItemPixelWidth"
! The width of the document in pixels (ie Image width or Video frame width)
: by-PixelWidth ( query-spec -- string ) PixelWidth query-by-attribute ;
CONSTANT: PixelCount "kMDItemPixelCount"
! The total number of pixels in the document. Type is a CFNumber.
: by-PixelCount ( query-spec -- string ) PixelCount query-by-attribute ;
CONSTANT: ColorSpace "kMDItemColorSpace"
! What color space model is this document following
! (For example, are examples "RGB", "CMYK", "YUV", "YCbCr")
: by-ColorSpace ( query-spec -- string ) ColorSpace query-by-attribute ;
CONSTANT: BitsPerSample "kMDItemBitsPerSample"
! Number of bits per sample
! For example bit depth of an image (8-bit, 16-bit etc..) or bit
! depth per audio sample of uncompressed audio data (8, 16, 24, 32,
! 64, etc..)
: by-BitsPerSample ( query-spec -- string ) BitsPerSample query-by-attribute ;
CONSTANT: FlashOnOff "kMDItemFlashOnOff"
! Indicates if the flash was used to take the picture. 0 means flash did not fire
: by-FlashOnOff ( query-spec -- string ) FlashOnOff query-by-attribute ;
CONSTANT: FocalLength "kMDItemFocalLength"
! The actual focal length of the lens in mm.
: by-FocalLength ( query-spec -- string ) FocalLength query-by-attribute ;
CONSTANT: AcquisitionMake "kMDItemAcquisitionMake"
! Device make that was used to acquire this document
: by-AcquisitionMake ( query-spec -- string ) AcquisitionMake query-by-attribute ;
CONSTANT: AcquisitionModel "kMDItemAcquisitionModel"
! Device model that was used to acquire this document
: by-AcquisitionModel ( query-spec -- string ) AcquisitionModel query-by-attribute ;
CONSTANT: ISOSpeed "kMDItemISOSpeed"
! The ISO Speed the camera was set to when the image was
! taken. Examples are 100, 200, 400, etc.
: by-ISOSpeed ( query-spec -- string ) ISOSpeed query-by-attribute ;
CONSTANT: Orientation "kMDItemOrientation"
! The orientation of the data. Values are 0 is "Landscape" or 1 is "Portrait"
: by-Orientation ( query-spec -- string ) Orientation query-by-attribute ;
CONSTANT: LayerNames "kMDItemLayerNames"
! The names of the various layers in the file
: by-LayerNames ( query-spec -- string ) LayerNames query-by-attribute ;
CONSTANT: WhiteBalance "kMDItemWhiteBalance"
! The white balance setting of the camera when the image was
! acquired. 0 is auto white balance and 1 is manual
: by-WhiteBalance ( query-spec -- string ) WhiteBalance query-by-attribute ;
CONSTANT: Aperture "kMDItemAperture"
! The size of the lens aperture as a log-scale APEX value
! when the image was acquired.
: by-Aperture ( query-spec -- string ) Aperture query-by-attribute ;
CONSTANT: ProfileName "kMDItemProfileName"
! Name of the color profile used for the image
: by-ProfileName ( query-spec -- string ) ProfileName query-by-attribute ;
CONSTANT: ResolutionWidthDPI "kMDItemResolutionWidthDPI"
! Resolution width of this image in DPI
: by-ResolutionWidthDPI ( query-spec -- string ) ResolutionWidthDPI query-by-attribute ;
CONSTANT: ResolutionHeightDPI "kMDItemResolutionHeightDPI"
! Resolution height of this image in DPI
: by-ResolutionHeightDPI ( query-spec -- string ) ResolutionHeightDPI query-by-attribute ;
CONSTANT: ExposureMode "kMDItemExposureMode"
! Mode that was used for the exposure. 0 is auto exposure, 1 is
! manual, and 2 is auto bracket.
: by-ExposureMode ( query-spec -- string ) ExposureMode query-by-attribute ;
CONSTANT: ExposureTimeSeconds "kMDItemExposureTimeSeconds"
! Time that the lens was open during exposure
: by-ExposureTimeSeconds ( query-spec -- string ) ExposureTimeSeconds query-by-attribute ;
CONSTANT: EXIFVersion "kMDItemEXIFVersion"
! The verion of the EXIF header that was used to generate the metadata
: by-EXIFVersion ( query-spec -- string ) EXIFVersion query-by-attribute ;
CONSTANT: EXIFGPSVersion "kMDItemEXIFGPSVersion"
! The version of GPSInfoIFD header that was used to generate the metadata
! CONSTANT: EXIFGPSVersion "kMDItemEXIFGPSVersion"
! The version of GPSInfoIFD in EXIF used to generate the metadata.
: by-EXIFGPSVersion ( query-spec -- string ) EXIFGPSVersion query-by-attribute ;
CONSTANT: Codecs "kMDItemCodecs"
! The codecs used to encode/decode the media
: by-Codecs ( query-spec -- string ) Codecs query-by-attribute ;
CONSTANT: MediaTypes "kMDItemMediaTypes"
! Media types present in the content
: by-MediaTypes ( query-spec -- string ) MediaTypes query-by-attribute ;
CONSTANT: Streamable "kMDItemStreamable"
! Whether the content is prepared for streaming
: by-Streamable ( query-spec -- string ) Streamable query-by-attribute ;
CONSTANT: TotalBitRate "kMDItemTotalBitRate"
! The total byte rate (audio & video combined) of the media
: by-TotalBitRate ( query-spec -- string ) TotalBitRate query-by-attribute ;
CONSTANT: VideoBitRate "kMDItemVideoBitRate"
! The video byte rate
: by-VideoBitRate ( query-spec -- string ) VideoBitRate query-by-attribute ;
CONSTANT: AudioBitRate "kMDItemAudioBitRate"
! The audio byte rate
: by-AudioBitRate ( query-spec -- string ) AudioBitRate query-by-attribute ;
CONSTANT: DeliveryType "kMDItemDeliveryType"
! Delivery type Fast start or RTSP
: by-DeliveryType ( query-spec -- string ) DeliveryType query-by-attribute ;
CONSTANT: Album "kMDItemAlbum"
! The title for a collection of media. This is analagous to a record album,
! or photo album whichs are collections of audio or images. Type is a CFString.
: by-Album ( query-spec -- string ) Album query-by-attribute ;
CONSTANT: HasAlphaChannel "kMDItemHasAlphaChannel"
! Boolean indicating if this image file has an alpha channel. Type is
! a CFBoolean.
: by-HasAlphaChannel ( query-spec -- string ) HasAlphaChannel query-by-attribute ;
CONSTANT: RedEyeOnOff "kMDItemRedEyeOnOff"
! Indicates if the flash was used to take the picture. 0 means no
! red-eye reduction mode or unknown. 1 means red-eye reduction
! supported.
: by-RedEyeOnOff ( query-spec -- string ) RedEyeOnOff query-by-attribute ;
CONSTANT: MeteringMode "kMDItemMeteringMode"
! The metering mode (Unknown, Average, CenterWeightedAverage, Spot,
! MultiSpot, Pattern, Partial)
: by-MeteringMode ( query-spec -- string ) MeteringMode query-by-attribute ;
CONSTANT: MaxAperture "kMDItemMaxAperture"
! The smallest F number of the lens. The unit is the APEX
! value. Ordinarily it is given in the range of 00.00 to 99.99.
: by-MaxAperture ( query-spec -- string ) MaxAperture query-by-attribute ;
CONSTANT: FNumber "kMDItemFNumber"
! The focal length of the lens divided by the diameter of the aperture
! when the image was acquired.
: by-FNumber ( query-spec -- string ) FNumber query-by-attribute ;
CONSTANT: ExposureProgram "kMDItemExposureProgram"
! The class of the program used by the camera to set exposure when
! the picture is taken (Manual, Normal, Aperture priority, ...)
: by-ExposureProgram ( query-spec -- string ) ExposureProgram query-by-attribute ;
CONSTANT: ExposureTimeString "kMDItemExposureTimeString"
! The time of the exposure.
: by-ExposureTimeString ( query-spec -- string ) ExposureTimeString query-by-attribute ;
CONSTANT: Headline "kMDItemHeadline"
! A publishable entry providing a synopsis of the contents of the
! objectdata.
: by-Headline ( query-spec -- string ) Headline query-by-attribute ;
CONSTANT: Instructions "kMDItemInstructions"
! Other editorial instructions concerning the use of the objectdata,
! such as embargoes and warnings.
: by-Instructions ( query-spec -- string ) Instructions query-by-attribute ;
CONSTANT: City "kMDItemCity"
! Identifies city of objectdata origin according to guidelines
! established by the provider.
: by-City ( query-spec -- string ) City query-by-attribute ;
CONSTANT: StateOrProvince "kMDItemStateOrProvince"
! Identifies Province/State of origin according to guidelines
! established by the provider.
: by-StateOrProvince ( query-spec -- string ) StateOrProvince query-by-attribute ;
CONSTANT: Country "kMDItemCountry"
! Provides full, publishable, name of the country/primary location
! where the intellectual property of the objectdata was created,
! according to guidelines of the provider.
: by-Country ( query-spec -- string ) Country query-by-attribute ;
CONSTANT: Altitude "kMDItemAltitude"
! The altitude of the item in meters above sea level, expressed
! using the WGS84 datum. Negative values lie below sea level.
: by-Altitude ( query-spec -- string ) Altitude query-by-attribute ;
CONSTANT: Latitude "kMDItemLatitude"
! The latitude of the item in degrees north of the equator, expressed
! using the WGS84 datum. Negative values lie south of the equator.
: by-Latitude ( query-spec -- string ) Latitude query-by-attribute ;
CONSTANT: Longitude "kMDItemLongitude"
! The longitude of the item in degrees east of the prime meridian,
! expressed using the WGS84 datum. Negative values lie west of the prime meridian.
: by-Longitude ( query-spec -- string ) Longitude query-by-attribute ;
CONSTANT: Timestamp "kMDItemTimestamp"
! The timestamp on the item. This generally is used to indicate the time at
! which the event captured by the item took place.
: by-Timestamp ( query-spec -- string ) Timestamp query-by-attribute ;
CONSTANT: Speed "kMDItemSpeed"
! The speed of the item, in kilometers per hour.
: by-Speed ( query-spec -- string ) Speed query-by-attribute ;
CONSTANT: GPSTrack "kMDItemGPSTrack"
! The direction of travel of the item, in degrees from true north.
: by-GPSTrack ( query-spec -- string ) GPSTrack query-by-attribute ;
CONSTANT: ImageDirection "kMDItemImageDirection"
! The direction of the item's image, in degrees from true north.
: by-ImageDirection ( query-spec -- string ) ImageDirection query-by-attribute ;
CONSTANT: NamedLocation "kMDItemNamedLocation"
! The name of the location or point of interest associated with the item.
! The name may be user provided.
: by-NamedLocation ( query-spec -- string ) NamedLocation query-by-attribute ;
CONSTANT: TextContent "kMDItemTextContent"
! Contains the text content of the document. Type is a CFString.
: by-TextContent ( query-spec -- string ) TextContent query-by-attribute ;
CONSTANT: DisplayName "kMDItemDisplayName"
! This is the localized version of the LaunchServices call
! LSCopyDisplayNameForURL()/LSCopyDisplayNameForRef().
: by-DisplayName ( query-spec -- string ) DisplayName query-by-attribute ;
CONSTANT: FSName "kMDItemFSName"
! This is the file name of the MDItemRef. Type is a CFString
! WITH SPACES IN FILENAME,E.G., "Finding Joy in Combinators.pdf" by-FSName mdfind
: by-FSName ( query-spec -- string ) FSName query-by-attribute ;
CONSTANT: Path "kMDItemPath"
! This is the complete path to the MDItemRef. Type is a CFString.
: by-Path ( query-spec -- string ) Path query-by-attribute ;
CONSTANT: FSSize "kMDItemFSSize"
! The total logical size of the file (data and resources) on disk in bytes. Type is a CFNumber.
: by-FSSize ( query-spec -- string ) FSSize query-by-attribute ;
CONSTANT: FSCreationDate "kMDItemFSCreationDate"
! This is the date that the file was created. Type is a CFDate.
: by-FSCreationDate ( query-spec -- string ) FSCreationDate query-by-attribute ;
CONSTANT: FSContentChangeDate "kMDItemFSContentChangeDate"
! This is the date the the file content last changed. This is a CFDate.
: by-FSContentChangeDate ( query-spec -- string ) FSContentChangeDate query-by-attribute ;
CONSTANT: FSOwnerUserID "kMDItemFSOwnerUserID"
! User-id of owner of the file. Type is a CFNumber.
: by-FSOwnerUserID ( query-spec -- string ) FSOwnerUserID query-by-attribute ;
CONSTANT: FSOwnerGroupID "kMDItemFSOwnerGroupID"
! Group-id of owner of the file. Type is a CFNumber.
: by-FSOwnerGroupID ( query-spec -- string ) FSOwnerGroupID query-by-attribute ;
CONSTANT: FSExists "kMDItemFSExists" ! *** DEPRECATED ***
! Boolean indicating if this MDItem references a file that still
! exists. The file that the MDItem references might have been
! deleted. Type is a CFBoolean.
: by-FSExists ( query-spec -- string ) FSExists query-by-attribute ;
CONSTANT: FSIsReadable "kMDItemFSIsReadable" ! *** DEPRECATED ***
! Boolean indicating if this file is readable. Type is a CFBoolean.
: by-FSIsReadable ( query-spec -- string ) FSIsReadable query-by-attribute ;
CONSTANT: FSIsWriteable "kMDItemFSIsWriteable" ! *** DEPRECATED ***
! Boolean indicating if this file is writable. Type is a CFBoolean.
: by-FSIsWriteable ( query-spec -- string ) FSIsWriteable query-by-attribute ;
CONSTANT: FSNodeCount "kMDItemFSNodeCount"
! Number of files in directory. Type is a CFNumber.
: by-FSNodeCount ( query-spec -- string ) FSNodeCount query-by-attribute ;
CONSTANT: FSHasCustomIcon "kMDItemFSHasCustomIcon"
! Boolean indicating if this file has a custom icon. Type is a CFBoolean.
: by-FSHasCustomIcon ( query-spec -- string ) FSHasCustomIcon query-by-attribute ;
CONSTANT: FSIsExtensionHidden "kMDItemFSIsExtensionHidden"
! Boolean indicating if this file has its extension hidden. Type is a CFBoolean.
: by-FSIsExtensionHidden ( query-spec -- string ) FSIsExtensionHidden query-by-attribute ;
CONSTANT: FSIsStationery "kMDItemFSIsStationery"
! Boolean indicating if this file is stationery. Type is a CFBoolean.
: by-FSIsStationery ( query-spec -- string ) FSIsStationery query-by-attribute ;
CONSTANT: FSInvisible "kMDItemFSInvisible"
! Boolean indicating if this file is visible. Type is a CFBoolean.
: by-FSInvisible ( query-spec -- string ) FSInvisible query-by-attribute ;
CONSTANT: FSLabel "kMDItemFSLabel"
! Number indicating which finder label is in use (0-7). Type is a CFNumber.
: by-FSLabel ( query-spec -- string ) FSLabel query-by-attribute ;
CONSTANT: AudioSampleRate "kMDItemAudioSampleRate"
! The sample rate of the audio data contained in the file. The sample rate is a
! float value representing hz (audio_frames/second). For example: 44100.0, 22254.54.
! Type is a CFNumber (float).
: by-AudioSampleRate ( query-spec -- string ) AudioSampleRate query-by-attribute ;
CONSTANT: AudioChannelCount "kMDItemAudioChannelCount"
! The number of channels in the audio data contained in the file. This item only represents
! the number of discreet channels of audio data found in the file. It does not indicate
! any configuration of the data in regards to a user's speaker setup.
! Type is a CFNumber (integer).
: by-AudioChannelCount ( query-spec -- string ) AudioChannelCount query-by-attribute ;
CONSTANT: Tempo "kMDItemTempo"
! The tempo of the music contained in the audio file in Beats Per Minute.
! Type is a CFNumber (float).
: by-Tempo ( query-spec -- string ) Tempo query-by-attribute ;
CONSTANT: KeySignature "kMDItemKeySignature"
! The musical key of the song/composition contained in an audio file.
! For example: C, Dm, F#m, Bb. Type is a CFString.
: by-KeySignature ( query-spec -- string ) KeySignature query-by-attribute ;
CONSTANT: TimeSignature "kMDItemTimeSignature"
! The time signature of the musical composition contained in the audio/MIDI file.
! For example: "4/4", "7/8". Type is a CFString.
: by-TimeSignature ( query-spec -- string ) TimeSignature query-by-attribute ;
CONSTANT: AudioEncodingApplication "kMDItemAudioEncodingApplication"
! The name of the application that encoded the data contained in the audio file.
! Type is a CFString.
: by-AudioEncodingApplication ( query-spec -- string ) AudioEncodingApplication query-by-attribute ;
CONSTANT: Composer "kMDItemComposer"
! The composer of the song/composition contained in the audio file.
! Type is a CFString.
: by-Composer ( query-spec -- string ) Composer query-by-attribute ;
CONSTANT: Lyricist "kMDItemLyricist"
! The lyricist/text writer for song/composition contained in the audio file.
! Type is a CFString.
: by-Lyricist ( query-spec -- string ) Lyricist query-by-attribute ;
CONSTANT: AudioTrackNumber "kMDItemAudioTrackNumber"
! The track number of a song/composition when it is part of an album (kMDItemAlbum).
! Type is a CFNumber (integer).
: by-AudioTrackNumber ( query-spec -- string ) AudioTrackNumber query-by-attribute ;
CONSTANT: RecordingDate "kMDItemRecordingDate"
! The recording date of the song/composition. This information differs from
! the kMDItemContentCreationDate attribute as it indicates the date that the
! 'art' was created, in contrast to ContentCreationDate which for example, could indicate
! the creation date of an edited or 'mastered' version of the original art.
! Type is a CFDate.
: by-RecordingDate ( query-spec -- string ) RecordingDate query-by-attribute ;
CONSTANT: MusicalGenre "kMDItemMusicalGenre"
! The musical genre of the song/composition contained in the audio file.
! For example: Jazz, Pop, Rock, Classical. Type is a CFString.
: by-MusicalGenre ( query-spec -- string ) MusicalGenre query-by-attribute ;
CONSTANT: IsGeneralMIDISequence "kMDItemIsGeneralMIDISequence"
! This attribute indicates whether the MIDI sequence contained in the file
! is setup for use with a General MIDI device. Type is a CFBoolean.
: by-IsGeneralMIDISequence ( query-spec -- string ) IsGeneralMIDISequence query-by-attribute ;
CONSTANT: RecordingYear "kMDItemRecordingYear"
! This attribute indicates what year the item was recorded on.
! Type is a CFNumber
: by-RecordingYear ( query-spec -- string ) RecordingYear query-by-attribute ;
CONSTANT: Organizations "kMDItemOrganizations"
! Used to indicate company/Organization that created the document.
! Type is a CFArray of CFStrings.
: by-Organizations ( query-spec -- string ) Organizations query-by-attribute ;
CONSTANT: Languages "kMDItemLanguages"
! Used to designate the languages of the intellectual content of the
! resource. Recommended best practice for the values of the Language
! element is defined by RFC 3066.
! Type is a CFArray of CFStrings.
: by-Languages ( query-spec -- string ) Languages query-by-attribute ;
CONSTANT: Rights "kMDItemRights"
! Used to provide a link to information about rights held in and
! over the resource. Typically a Rights element will contain a
! rights management statement for the resource, or reference a
! service providing such information. Rights information often
! encompasses Intellectual Property Rights (IPR), Copyright, and
! various Property Rights. If the rights element is absent, no
! assumptions can be made about the status of these and other rights
! with respect to the resource. Type is a CFString type.
: by-Rights ( query-spec -- string ) Rights query-by-attribute ;
CONSTANT: Publishers "kMDItemPublishers"
! Used to designate the entity responsible for making the resource
! available. Examples of a Publisher include a person, an
! organization, or a service. Typically, the name of a Publisher
! should be used to indicate the entity. Type is a CFArray of CFStrings.
: by-Publishers ( query-spec -- string ) Publishers query-by-attribute ;
CONSTANT: Contributors "kMDItemContributors"
! Used to designate the entity responsible for making contributions
! to the content of the resource. Examples of a Contributor include
! a person, an organization or a service. Typically, the name of a
! Contributor should be used to indicate the entity. Type is a
! CFArray of CFStrings.
: by-Contributors ( query-spec -- string ) Contributors query-by-attribute ;
CONSTANT: Coverage "kMDItemCoverage"
! Used to designate the extent or scope of the content of the
! resource. Coverage will typically include spatial location (a
! place name or geographic co-ordinates), temporal period (a period
! label, date, or date range) or jurisdiction (such as a named
! administrative entity). Recommended best practice is to select a
! value from a controlled vocabulary, and that, where appropriate,
! named places or time periods be used in preference to numeric
! identifiers such as sets of co-ordinates or date ranges. Type is a
! CFString.
: by-Coverage ( query-spec -- string ) Coverage query-by-attribute ;
CONSTANT: Subject "kMDItemSubject"
! Subject of the this item. Type is a CFString.
: by-Subject ( query-spec -- string ) Subject query-by-attribute ;
CONSTANT: Theme "kMDItemTheme"
! Theme of the this item. Type is a CFString.
: by-Theme ( query-spec -- string ) Theme query-by-attribute ;
CONSTANT: Description "kMDItemDescription"
! An account of the content of the resource. Description may include
! but is not limited to: an abstract, table of contents, reference
! to a graphical representation of content or a free-text account of
! the content. Type is a CFString.
: by-Description ( query-spec -- string ) Description query-by-attribute ;
CONSTANT: Identifier "kMDItemIdentifier"
! Used to reference to the resource within a given
! context. Recommended best practice is to identify the resource by
! means of a string or number conforming to a formal identification
! system. Type is a CFString.
: by-Identifier ( query-spec -- string ) Identifier query-by-attribute ;
CONSTANT: Audiences "kMDItemAudiences"
! A class of entity for whom the resource is intended or useful. A
! class of entity may be determined by the creator or the publisher
! or by a third party. Type is a CFArray of CFString.
: by-Audiences ( query-spec -- string ) Audiences query-by-attribute ;
CONSTANT: NumberOfPages "kMDItemNumberOfPages"
! Number of pages in the item. Type is a CFNumberRef
: by-NumberOfPages ( query-spec -- string ) NumberOfPages query-by-attribute ;
CONSTANT: PageWidth "kMDItemPageWidth"
! Width in points (72 points per inch) of the document page
! (first page only for PDF's - other pages within the PDF may
! not be the same width). Type is a CFNumber.
: by-PageWidth ( query-spec -- string ) PageWidth query-by-attribute ;
CONSTANT: PageHeight "kMDItemPageHeight"
! Height in points (72 points per inch) of the document page
! (first page only for PDF's - other pages within the PDF may
! not be the same height). Type is a CFNumber.
: by-PageHeight ( query-spec -- string ) PageHeight query-by-attribute ;
CONSTANT: SecurityMethod "kMDItemSecurityMethod"
! Security (encryption) method used in the file, for a PDF will be one of:
! "Password Encrypted" or "None". Type is a CFStrings.!
: by-SecurityMethod ( query-spec -- string ) SecurityMethod query-by-attribute ;
CONSTANT: Creator "kMDItemCreator"
! Application used to create the document content (e.g. "Word",
! "Framemaker", etc.). Type is a CFStrings.
: by-Creator ( query-spec -- string ) Creator query-by-attribute ;
CONSTANT: EncodingApplications "kMDItemEncodingApplications"
! Software used to convert the original content into a PDF stream
! (e.g. "Distiller", etc.). Type is a Array of CFStrings.
: by-EncodingApplications ( query-spec -- string ) EncodingApplications query-by-attribute ;
CONSTANT: DueDate "kMDItemDueDate"
! Date this item is due. Type is a CFDate.
: by-DueDate ( query-spec -- string ) DueDate query-by-attribute ;
CONSTANT: StarRating "kMDItemStarRating"
! User rate of this item like iTunes. Type is a CFNumber
: by-StarRating ( query-spec -- string ) StarRating query-by-attribute ;
CONSTANT: PhoneNumbers "kMDItemPhoneNumbers"
! Phone numbers for this item. Type is an Array of CFStrings.
: by-PhoneNumbers ( query-spec -- string ) PhoneNumbers query-by-attribute ;
CONSTANT: EmailAddresses "kMDItemEmailAddresses"
! Email addresses for this item. Type is an Array of CFStrings.
: by-EmailAddresses ( query-spec -- string ) EmailAddresses query-by-attribute ;
CONSTANT: InstantMessageAddresses "kMDItemInstantMessageAddresses"
! Instant message addresses for this item. Type is an Array of CFStrings.
: by-InstantMessageAddresses ( query-spec -- string )
InstantMessageAddresses query-by-attribute ;
CONSTANT: Kind "kMDItemKind"
! Kind that this item represents. Type is a CFString.
: by-Kind ( query-spec -- string ) Kind query-by-attribute ;
CONSTANT: Recipients "kMDItemRecipients"
! This attribute indicates the recipients of this item. Type is a Array of CFStrings
: by-Recipients ( query-spec -- string ) Recipients query-by-attribute ;
CONSTANT: FinderComment "kMDItemFinderComment"
! These are the finder comments for this item. Type is a CFString.
: by-FinderComment ( query-spec -- string ) FinderComment query-by-attribute ;
CONSTANT: Fonts "kMDItemFonts"
! Array of font names used in the item. Attribute would store the Fonts
! full name, the postscript name or the font family name based on whats available.
! Type is an Array of CFStrings.
: by-Fonts ( query-spec -- string ) Fonts query-by-attribute ;
CONSTANT: AppleLoopsRootKey "kMDItemAppleLoopsRootKey"
! Meta data attribute that stores the root note or tonic for the
! loop, and does not include the scale type. The root key is
! represented as follows: "C" "C#/Db" "D" "D#/Eb" "E" "F"
! "F#/Gb" "G" "G#/Ab" "A" "A#/Bb" "B" "NoKey"
: by-AppleLoopsRootKey ( query-spec -- string ) AppleLoopsRootKey query-by-attribute ;
CONSTANT: AppleLoopsKeyFilterType "kMDItemAppleLoopsKeyFilterType"
! Meta data attribute that stores key filtering information
! about a loop. Loops are matched against projects that often in
! a major or minor key. To assist users in identifying loops
! that will "fit" with their compositions, loops can be tagged
! with one of the following key filters: "AnyKey" "Minor"
! "Major" "NeitherKey" "BothKeys". AnyKey means that it fits
! with anything (whether in a major key, minor key or
! neither). Minor fits with compositions in a minor
! key. NeitherKey doesn't work well with compositions that are
! in major or minor key. BothKeys means it fits with major or
! minor key.
: by-AppleLoopsKeyFilterType ( query-spec -- string )
AppleLoopsKeyFilterType query-by-attribute ;
CONSTANT: AppleLoopsLoopMode "kMDItemAppleLoopsLoopMode"
! Meta data attribute that stores how a file should be
! played. Tagged files can either be loops or non-loops (e.g., a
! cymbal crash). "Looping" indicates if the file should be
! treated as a loop. "Non-looping" indicates the file should not
! be treated as a loop.
: by-AppleLoopsLoopMode ( query-spec -- string ) AppleLoopsLoopMode query-by-attribute ;
CONSTANT: AppleLoopDescriptors "kMDItemAppleLoopDescriptors"
! Meta data attribute that stores multiple pieces of descriptive
! information about a loop. Besides genre and instrument, files
! can contain descriptive information that help users in
! refining searches. A file can have multiple descriptors
! associated with them, though they come in pairs of antonyms
! (e.g., "Acoustic" and "Electric"). A file can have zero or
! more descriptors.
: by-AppleLoopDescriptors ( query-spec -- string ) AppleLoopDescriptors query-by-attribute ;
CONSTANT: MusicalInstrumentCategory "kMDItemMusicalInstrumentCategory"
! Meta data attribute that stores the category of
! instrument. Files should have an instrument associated with
! them ("Other Instrument" is provided as a catch-all). For some
! categories, like "Keyboards" there are instrument names which
! provide a more detailed instrument definition (e.g., Piano,
! Organ, etc.)
: by-MusicalInstrumentCategory ( query-spec -- string )
MusicalInstrumentCategory query-by-attribute ;
CONSTANT: MusicalInstrumentName "kMDItemMusicalInstrumentName"
! Meta data attribute that stores the name of instrument
! (relative to the instrument category) Files can have an
! instrument name associated with them if they have certain
! instrument categories (e.g., the category Percussion has
! multiple instruments, including Conga and Bongo).
: by-MusicalInstrumentName ( query-spec -- string ) MusicalInstrumentName query-by-attribute ;
CONSTANT: CFBundleIdentifier "kMDItemCFBundleIdentifier"
! If this item is a bundle, then this is the CFBundleIdentifier
: by-CFBundleIdentifier ( query-spec -- string ) CFBundleIdentifier query-by-attribute ;
CONSTANT: Information "kMDItemInformation"
! Information about the item
: by-Information ( query-spec -- string ) Information query-by-attribute ;
CONSTANT: Director "kMDItemDirector"
! Director of the movie
: by-Director ( query-spec -- string ) Director query-by-attribute ;
CONSTANT: Producer "kMDItemProducer"
! Producer of the content
: by-Producer ( query-spec -- string ) Producer query-by-attribute ;
CONSTANT: Genre "kMDItemGenre"
! Genre of the movie
: by-Genre ( query-spec -- string ) Genre query-by-attribute ;
CONSTANT: Performers "kMDItemPerformers"
! Performers in the movie
: by-Performers ( query-spec -- string ) Performers query-by-attribute ;
CONSTANT: OriginalFormat "kMDItemOriginalFormat"
! Original format of the movie
: by-OriginalFormat ( query-spec -- string ) OriginalFormat query-by-attribute ;
CONSTANT: OriginalSource "kMDItemOriginalSource"
! Original source of the movie
: by-OriginalSource ( query-spec -- string ) OriginalSource query-by-attribute ;
CONSTANT: AuthorEmailAddresses "kMDItemAuthorEmailAddresses"
! This attribute indicates the author of the emails message addresses. (This is always
! the email address, and not the human readable version)
: by-AuthorEmailAddresses ( query-spec -- string ) AuthorEmailAddresses query-by-attribute ;
CONSTANT: RecipientEmailAddresses "kMDItemRecipientEmailAddresses"
! This attribute indicates the reciepients email addresses. (This is always the email
! address, and not the human readable version).
: by-RecipientEmailAddresses ( query-spec -- string )
RecipientEmailAddresses query-by-attribute ;
CONSTANT: AuthorAddresses "kMDItemAuthorAddresses"
! This attribute indicates the author addresses of the document.
: by-AuthorAddresses ( query-spec -- string ) AuthorAddresses query-by-attribute ;
CONSTANT: RecipientAddresses "kMDItemRecipientAddresses"
! This attribute indicates the recipient addresses of the document.
: by-RecipientAddresses ( query-spec -- string ) RecipientAddresses query-by-attribute ;
CONSTANT: ContentType "kMDItemContentType"
: by-ContentType ( query-spec -- string ) ContentType query-by-attribute ;
CONSTANT: AlternateNames "kMDItemAlternateNames"
! Alternate display names, Alternate names of the file
: by-AlternateNames ( query-spec -- string ) AlternateNames query-by-attribute ;
CONSTANT: AttributeChangeDate "kMDItemAttributeChangeDate"
: by-AttributeChangeDate ( query-spec -- string ) AttributeChangeDate query-by-attribute ;
CONSTANT: Authors "kMDItemAuthors"
! 'Authors','Authors of this item', 'author, from, with, by'
: by-Authors ( query-spec -- string ) Authors query-by-attribute ;
CONSTANT: ContentTypeTree "kMDItemContentTypeTree"
: by-ContentTypeTree ( query-spec -- string ) ContentTypeTree query-by-attribute ;
CONSTANT: DocumentLineage "kMDItemDocumentLineage"
: by-DocumentLineage ( query-spec -- string ) DocumentLineage query-by-attribute ;
CONSTANT: Editors "kMDItemEditors"
! 'Editors', 'Editors of this item', 'editor'
: by-Editors ( query-spec -- string ) Editors query-by-attribute ;
CONSTANT: IsQuarantined "kMDItemIsQuarantined"
: by-IsQuarantined ( query-spec -- string ) IsQuarantined query-by-attribute ;
CONSTANT: IsScreenCapture "kMDItemIsScreenCapture"
: by-IsScreenCapture ( query-spec -- string ) IsScreenCapture query-by-attribute ;
CONSTANT: Keywords "kMDItemKeywords"
: by-Keywords ( query-spec -- string ) Keywords query-by-attribute ;
CONSTANT: Participants "kMDItemParticipants"
! 'Participants', 'Participants in this item
: by-Participants ( query-spec -- string ) Participants query-by-attribute ;
CONSTANT: Projects "kMDItemProjects"
! 'Projects', Projects this item is part of'
: by-Projects ( query-spec -- string ) Projects query-by-attribute ;
CONSTANT: ScreenCaptureType "kMDItemScreenCaptureType"
: by-ScreenCaptureType ( query-spec -- string ) ScreenCaptureType query-by-attribute ;
CONSTANT: SupportFileType "kMDItemSupportFileType"
: by-SupportFileType ( query-spec -- string ) SupportFileType query-by-attribute ;
CONSTANT: Title "kMDItemTitle"
! 'Title', 'Title of this item', 'title'
: by-Title ( query-spec -- string ) Title query-by-attribute ;
CONSTANT: UsedDates "kMDItemUsedDates"
! 'Used dates', 'Dates when this item was used', 'used, date'
: by-UsedDates ( query-spec -- string ) UsedDates query-by-attribute ;
CONSTANT: URL "kMDItemURL"
! Url of the item
: by-URL ( query-spec -- string ) URL query-by-attribute ;
: double-quote ( -- string ) \ " name>> ;
! **************************** ANCILLARY INFO, MOTLEY EXAMPLES ****************************
! instruct MDS to clear out the metadata cache and rebuild from scratch using this command run from Terminal: sudo mdutil -avE
!
! *** AT COMMAND LINE ON OS X 10.6.8 ***
! mdfind USAGE:
! ➜ ~ git:(master) ✗ mdfind
! mdfind: no query specified.
! Usage: mdfind [-live] [-count] [-onlyin directory] [-name fileName | -s smartFolderName | query]
! list the files matching the query
! query can be an expression or a sequence of words
! -live Query should stay active
! -count Query only reports matching items count
! -onlyin <dir> Search only within given directory
! -name <name> Search on file name only
! -s <name> Show contents of smart folder <name>
! -0 Use NUL (``\0'') as a path separator, for use with xargs -0.
! ***NOT AVAILABLE ON 10.6.8??? --
! -literal Force the provided query string to be taken as a literal query
! string, without interpretation.
!
! -interpret Force the provided query string to be interpreted as if the user
! had typed the string into the Spotlight menu.
! For example, the string "search" would produce the following
! query string:
! (* = search* cdw || kMDItemTextContent = search* cdw)
!
!
! example: mdfind image (--OR mdfind "mdfind USAGE:" FOR PHRASES)
! example: mdfind -onlyin ~ image
! example: mdfind -name stdlib.h
! example: mdfind "kMDItemAuthor == '*MyFavoriteAuthor*'" (--OR E.G., mdfind 'kMDItemAuthor == "Henry David Thoreau"' )
! example: mdfind -live MyFavoriteAuthor
!
! ➜ ~ git:(master) ✗
! ***************** mdfind command line examples *****************
! name:file.txt
! kind:"jpeg image" (kind:jpg or *.jpg doesn't work)
! date:today
! date:"this week" (date:week doesn't work)
! modified:12/31/11
! kind:video AND size:<100000
! created:12/1/11-12/31/11
!
! Spotlight Keywords-
! These can be included in the query expression to limit the type
! of documents returned:
!
! Applications kind:application, kind:applications, kind:app
! Audio/Music kind:audio, kind:music
! Bookmarks kind:bookmark, kind:bookmarks
! Contacts kind:contact, kind:contacts
! Email kind:email, kind:emails, kind:mail message,
! kind:mail messages
! Folders kind:folder, kind:folders
! Fonts kind:font, kind:fonts
! iCal Events kind:event, kind:events
! iCal To Dos kind:todo, kind:todos, kind:to do, kind:to dos
! Images kind:image, kind:images
! Movies kind:movie, kind:movies
! PDF kind:pdf, kind:pdfs
! Preferences kind:system preferences, kind:preferences
! Presentations kind:presentations, kind:presentation
!
! Date Keywords-
! These can be included in the query expression to limit the age
! of documents returned:
!
! date:today $time.today()
! date:yesterday .yesterday()
! *** POST TO Factor-talk LEFT OFF HERE **************
! date:this week .this_week()
! date:this month .this_month()
! date:this year .this_year()
! date:tomorrow .tomorrow()
! date:next month .next_month()
! date:next week .next_week()
! date:next year .next_year()
!
! Boolean Operators-
! By default mdfind will AND together elements of the query string.
!
! | (OR) To return items that match either word, use the pipe character:
! stringA|stringB
! - (NOT) To exclude documents that match a string -string
! == “equal”
! = “not equal”
! < and > “less” or “more than”
! <= and >= “less than or equal” or “more than or equal”
!
! lenin|trotsky will find documents mentioning either Lenin or Trotsky
! lenin(-stalin) will find documents mentioning Lenin, but not, thankfully, Stalin
! lenin|trotsky(-stalin) will find documents mentioning either Lenin or Trotsky, but not Stalin
!
! Returns all files with any metadata attribute value matching the string "image":
! $ mdfind image
!
! Return all files that contain "Len Deighton" in the kMDItemAuthor metadata attribute:
! $ mdfind "kMDItemAuthor == '*Len Deighton*'"
!
! Return all files with any metadata attribute value matching the string
! "skateboard". The find continues to run after gathering the initial results,
! providing a count of the number of files that match the query.
! $ mdfind -live skateboard
!
! Return all Microsoft.Word document files:
! $ mdfind "kMDItemContentType == 'com.microsoft.word.doc'"
!
! Return files where the composer name includes 'Eno'
! (non case sensitive search):
! $ mdfind 'kMDItemComposer = "*ENO*"c'
!
! Return all image files matching the words 'maude' and 'paris':
! $ mdfind "kind:images maude paris"
!
! Return all image files last edited yesterday:
! $ mdfind "kind:image date:yesterday"
!
! Return all files in the users home folder (~) that have been modified in the
! last 3 days:
! $ mdfind -onlyin ~ 'kMDItemFSContentChangeDate >= $time.today (-3)'
!
! mdfind '"exact phrase"'
!
! mdfind kMDItemFSName=\*.scpt
! mdfind 'kMDItemFSName=*' -onlyin . # doesn't include hidden files
! mdfind kMDItemFSName=.DS_Store -0 | xargs -0 rm
! mdfind -0 -onlyin ~/Music 'kMDItemFSName=*.mp3&&kMDItemAudioBitRate<=192000' | xargs -0 mdls -name kMDItemAlbum | sort | uniq
!
! mdfind kMDItemContentType=com.apple.application-bundle -onlyin /usr/local
! mdfind kMDItemContentTypeTree=com.apple.bundle
! mdfind kMDItemContentTypeTree=public.movie
!
! mdfind 'kMDItemTextContent="*expose*"cd' # ignore case and diacritics
! mdfind kMDItemTextContent=*LSUIElement* -onlyin ~/Projects/applepdfs/
!
! mdfind 'kMDItemFSSize>=5000&&kMDItemFSSize<=5005'
!
! mdfind 'kMDItemFSContentChangeDate>=$time.iso(2012-04-13T13:44Z)'
!
! mdfind 'kMDItemFSCreationDate>=$time.now(-3600)'
!
! mdfind 'kMDItemKind=*movie&&kMDItemPixelHeight>=720'
!
! mdfind 'kMDItemFSInvisible=1||kMDItemFSInvisible=0' -onlyin . # includes hidden files
!
! mdfind 'kMDItemURL=*web.archive.org*page*' -onlyin ~/Library/Caches/Metadata/Safari/History
!
! mdfind 'kMDItemFSSize>=1e8&&kMDItemContentTypeTree=public.directory'
!
! mdfind kind:pdf
!
! mdfind 'kMDItemFSLabel>0' # items with color labels
!
! mdfind -onlyin / # like -onlyin /Volumes/Macintosh\ HD
!
! mdfind "$(PlistBuddy -c 'Print RawQuery' test.savedSearch)"
!
! sudo mdfind com_apple_backup_excludeItem=com.apple.backupd
!
! *** N.B. - SOME EXAMPLES © Copyright SS64.com 1999-2013 Some rights reserved ***
@ajvondrak
Copy link

  1. Mind saving the gist with a file name & syntax highlighting set, like spotlight.factor? GitHub can syntax highlight Factor; for example: https://gist.github.com/ajvondrak/4158963
  2. Also, have you tried saving this to a file to see if it works when loaded as a vocab? Sometimes "copy/pasted into the listener" doesn't work, because the listener loads some extra vocabs and stuff. E.g., save the file in factor/work/spotlight/spotlight.factor and try to USE: spotlight.
  3. You've got a lot of long lines & tabs, particularly in the comments. Factor code is (by convention) line-wrapped at 64 characters & uses 4 spaces instead of tabs. See http://concatenative.org/wiki/view/Factor/Coding%20Style
  4. YOU YELL A LOT IN YOUR COMMENTS. :) Not that I exactly blame you, there's a lot of noise with the billions of constants & repetitive definitions.
  5. You seem to use the pattern "...dummy..." "y" "dummy" replace a lot, and a couple complex "" makes that use locals. How about just sprintf? See http://docs.factorcode.org/content/word-sprintf,formatting.html and http://docs.factorcode.org/content/word-printf%2Cformatting.html
  6. I'm not sure how others feel, but for something as hairy as mdfind's baked-in query language & all its metadata types, I reckon nothing's going to be much simpler than just having the user specify the query strings manually.

I count 142 (!) kMDItem* constants alone in the docs here: https://developer.apple.com/library/mac/documentation/Carbon/Reference/MDItemRef/Reference/reference.html#//apple_ref/doc/uid/TP40001202-CH3g-110577

What's simpler: maintaining a list of 142 Factor words & constants so that users can say by-Foo mdfind (and having to change the list as Apple's API changes), or just having a general word that works on strings like "Foo" mditem mdfind? Give people the building blocks for the queries so you don't have to worry about the nitty-gritty.

Really, I'd be happy with just

: mdfind ( query -- results )
    "mdfind" swap 2array utf8 [ lines ] with-process-reader ;

to start. Then querying is just like using mdfind normally, only slightly backwards:

"kMDItemFSName == '2013 Company Holiday Calendar.pdf'" mdfind

Notice that I use 2array to make an array-based launch descriptor. Even though the string I provided has spaces, it's OK---intentional, in fact, because I wind up making the same launch descriptor as if I had used the following string:

IN: scratchpad "mdfind \"kMDItemFSName == '2013 Company Holiday Calendar.pdf'\"" tokenize .
V{
    "mdfind"
    "kMDItemFSName == '2013 Company Holiday Calendar.pdf'"
}

Using 2array lets me get the same result as above, but I don't need to escape quotes inside of a string.

The power of such a library could be building up around the command options, rather than around mdfind's mess of a query language with a million header file constants. E.g., start building out words like

: mdfind-count ( query -- n )
    { "mdfind" "-count" } swap suffix
    utf8 [ readln string>number ] with-process-reader ;

: mdfind-onlyin ( query directory -- results )
    ... ;

! what have you

If you must have this list of header constants, at least get them more programmatically. E.g., use alien (http://docs.factorcode.org/content/article-alien.html) and call the actual API: http://lists.apple.com/archives/spotlight-dev/2005/Aug/msg00004.html

  1. I'm doubting they're necessary, but let me see if I can make heads or tails of escape-spaces? & escape-path?...

First, the names. See http://docs.factorcode.org/content/article-conventions.html These don't seem to be predicates. I think you want ?escape-spaces and ?escape-path. But even then, the question marks aren't really necessary for such words---there's nothing "maybe" about escaping spaces. If there aren't any spaces, you couldn't escape them if you wanted to; it's sort of implied.

Then there's your use of >byte-array BV{ } clone-like CHAR: x suffix! >string. An unwieldy piece of code that is the equivalent of a simple CHAR: x suffix or even "x" append. Even if you were trying to be destructive with this (using suffix!), it's failed because you have to use >byte-array and clone-like! Similarly, your but-last >byte-array BV{ } clone-like >string is just but-last.

In escape-spaces?, the check for " " swap subseq? is unnecessary. If there are no spaces, x " " split will just return { x }. And then { x } " " join will return x. But really, none of that is necessary---your own use of replace should've tipped you off!

In escape-path?, instead of last CHAR: / = not, you could say "/" tail? not. And instead of not [ ... ] when, you could say [ ... ] unless.

So, I think this is a simpler way to do all of that:

: escape-spaces ( string -- string' )
    " " "\\ " replace ;

: escape-path ( path -- path' )
    escape-spaces dup "/" tail? [ "/" append ] unless ;

Phew! That's all I've got, I think...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment