Automatically tagging files that were last opened more than x days ago
When a file is tagged in Finder it has an extended attribute set on it:
com.apple.metadata:_kMDItemUserTags
General Information
The easiest way I've found to apply a custom tag to a file programmatically is to use xattr
to get the value of a custom tag, not one of the default tags, and apply it to the target file(s) via a shell script. For example, I created a new custom tag named Review, giving it the color yellow. Its hex representation is:
62706C6973743030A101585265766965770A35080A0000000000000101000000000000000200000000000000000000000000000013
Hint: Mouse over and horizontal scroll to see full code.
To get the value of the custom tag's com.apple.metadata:_kMDItemUserTags
extended attribute, after having set it normally in Finder, the following example compound command was use in Terminal, e.g.:
xattr -px com.apple.metadata:_kMDItemUserTags "/path/to/file" | tr -d '\n' | tr -d ' '
Hint: Mouse over and horizontal scroll to see full code.
- Note: When using the above example compound command the prompt is not returned as normal and is directly after the hex string instead of being on the next line, so when copying the hex string make sure not to copy any of the prompt!
The output of the xattr
command to see standard output would be, e.g.:
$ xattr -l "/path/to/file"
com.apple.metadata:_kMDItemUserTags:
00000000 62 70 6C 69 73 74 30 30 A1 01 58 52 65 76 69 65 |bplist00..XRevie|
00000010 77 0A 35 08 0A 00 00 00 00 00 00 01 01 00 00 00 |w.5.............|
00000020 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 13 |.....|
00000035
$
Hint: Mouse over and horizontal scroll to see full code.
However, for this purpose just the hex string is wanted, hence the use of the -px
option previously, and why piping the output to the tr
command to delete newlines, \n
, and spaces is necessary.
Applying Custom Tag
To apply this custom tag in Terminal to a file for testing, use e.g.:
xattr -wx com.apple.metadata:_kMDItemUserTags '62706C6973743030A101585265766965770A35080A0000000000000101000000000000000200000000000000000000000000000013' "/path/to/file"
Hint: Mouse over and horizontal scroll to see full code.
-
Note: The
xattr
man page does show an example of copying the extended attribute from one directory to another, which can be applied to files too, however for a programmatic solution I prefer this method. Seeman xargs
in Terminal for additional information.
Programmatic Usage
This could be used in a bash
script or in Automator using a Run Shell Script action, however the Find Finder Items action and Filter Finder Items action in Automator has a bug with the Date last opened setting.
This leaves using the find
command or the mdfind
command, the latter being better at finding files for the Date Last Opened as shown in Finder in List view or the Get Info sheet for a given file, which is the kMDItemLastUsedDate
attribute used with the mdfind
command using a properly formed query. Note that mdfind
does require Spotlight Indexing of the target directory, and is turned on by default.
In Terminal, this compound command example uses mdfind
to locate files matching the query and its result it passed to xargs
to run xattr
on the files to apply the custom tag:
mdfind -0 -onlyin "$HOME/Documents" 'kMDItemLastUsedDate > $time.today(-7) && kMDItemLastUsedDate < $time.today(-6)' | xargs -0 -I % xattr -wx com.apple.metadata:_kMDItemUserTags '62706C6973743030A101585265766965770A35080A0000000000000101000000000000000200000000000000000000000000000013' %
Hint: Mouse over and horizontal scroll to see full code.
How this gets wrapped in a shell script or in Automator using a Run Shell Script action and scheduled to run at a regular interval really depends on how one intends to schedule it and other criteria surrounding how one intends to take into account its usage and other controls so as not to just run wild, if you will.
I would probably choose to use launchd
to schedule this as a bash
script and stay away from Automator, that is depending on what else one is wanting to be a part of the overall process.
For testing purposes, under macOS High Sierra, this is what I did:
1. Create a bash
script with the example mdfind
compound command from above.
In Terminal:
mkdir ~/bin
cd ~/bin
touch crtag
open -e crtag
The last command above should, by default, open crtag, for [C]ustom[R]eview[Tag], in TextEdit, in which the following lines were added:
#!/bin/bash
mdfind -0 -onlyin "$HOME/Documents" 'kMDItemLastUsedDate > $time.today(-7) && kMDItemLastUsedDate < $time.today(-6)' | xargs -0 -I % xattr -wx com.apple.metadata:_kMDItemUserTags '62706C6973743030A101585265766965770A35080A0000000000000101000000000000000200000000000000000000000000000013' %
Hint: Mouse over and horizontal scroll to see full code.
Saved the e.g. crtag document and closed it.
Back in Terminal, made crtag
executable, e.g.:
chmod 0755 crtag
Note: 0755
translates to: -rwxr-xr-x
2. Create a PLIST file for launchd
to run the e.g. crtag
shell script daily at the desired time.
In Terminal:
cd ~/Library/LaunchAgents
touch com.my.DateLastOpenedCustomReviewTag.plist
open -e com.my.DateLastOpenedCustomReviewTag.plist
The last command above should, by default, open com.my.DateLastOpenedCustomReviewTag.plist in TextEdit, in which the following lines were added:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:</string>
</dict>
<key>Label</key>
<string>com.my.DateLastOpenedCustomReviewTag</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/path/to/script</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
</array>
</dict>
</plist>
While setting /path/to/script
to the actual fully qualified pathname, e.g. /Users/me/bin/crtag
, and the time as shown in the <key>Hour</key>
, <integer>9</integer>
and <key>Minute</key>
, <integer>00</integer>
keys, which uses 24 Hour time.
Saved the e.g. com.my.DateLastOpenedCustomReviewTag.plist document and closed it.
Back in Terminal, loaded the e.g. com.my.DateLastOpenedCustomReviewTag.plist file for launchd
to run the shell script, per its settings:
launchctl load com.my.DateLastOpenedCustomReviewTag.plist
Now every day at e.g. 9:00 AM, the files meeting the mdfind
query will have the custom tag applied to them, which can be viewed in Finder from the Tags section on the Sidebar, or other Finder methods involving Tags.
Note: See the manual pages in Terminal for mdfind
, launchd
, launchctl
, tr
, xargs
and xattr
, e.g. man mdfind
. Also have a look at: File Metadata Query Expression Syntax