Move MS Office (Word, Excel and PowerPoint) files in 1 rule

From your noodle to other noodles. Talk about ways to get the most from Hazel. Even exchange recipes for the cool rules you've thought up. DO NOT POST YOUR QUESTIONS HERE.

Moderators: Mr_Noodle, Moderators

I work on a number of Word, Excel and PowerPoint files every day. Now, being a somewhat disorganised bloke, I often end up with a sprawling and erratic Desktop or Downloads folder with both files I am currently working on and others too old to remember what they actually are.

What I therefore want to do is move all Word, Excel and PowerPoint files that have not been modified in the previous two days to a separate folder. In Hazel, I can either set up one rule that will move any of these files as soon as they are seen (as you cant have a mixture of 'any' and 'all' conditions in a single rule), or set up multiple rules for every permutation of Office file, which would be a lot of work and a real pain to ensure worked correctly, especially if I wanted to 'reuse' the rule for other folders. But at least I could set the 'Date Last Modified' condition correctly.

C'est la vie. Well, not quite. I've come up with a single rule that will move any valid Office (really Word, Excel or PowerPoint) file that has not been modified for two days. Oh, yes.

As you may have guessed, this is going to involve a shell script, so pull on your scripting gloves and crank up your text editor. We're going to write an external (as opposed to embedded) script for this, simply because we can then easily use the same script in other Hazel rules, or directly from the command line or another script.

The following script checks to see if a given file or files are Office files and then moves those ones that are. It does not check the modification time -- that is best left to Hazel. In fact, the script checks each file it is given three times to determine whether it is a valid file: by the file extension, by Spotlight metadata, and by the very useful Unix file command. If any of these three methods return a positive, then the file will be moved to a set destination. It uses a couple of regular expressions, but this is to save on typing.

The script

Code: Select all

# -- Move MS Office files (Word, Excel and PowerPoint) to given location

# Use with Hazel with an 'Any File' condition or as a stand-alone script

# checks to see if the file to be processed is a known MS Office file by checking the
# extension, Spotlight metadata and the output of the 'file' command against a couple of regular
# expressions (regexs).
# The script checks for the following extensions: doc, docx, docm, dot, dotm, dotx, xls, xlsm,
# xlst, xlt, xltm, xltx, xla, xlam, xll, ppt, pptm, pptx, pps, ppsm, ppsx, pot, potm, potx, ppa
# and ppam. It also checks both Spotlight metadata and the output of 'file' for the substrings
# 'Word', 'Excel' or 'PowerPoint'. If any of these checks are positive, then the file is (probably)
# an Office file and is moved to the folder specified in $destFolder.

destFolder=$HOME/Documents/\!UNSORTED/MS\ Office  # The folder where the files should be moved to
extRegex='^(do[ct][mx]?|xl([st][mx]?|am?|l)|p((p[st]|ot)[mx]?|pam?))$'  # Regex for valid extensions
mdRegex='(Word|Excel|PowerPoint)'  # Regex for returned metadata

until [[ -z "$1" ]]  # Loop until no more positional parameters to process
   extension=$(echo ${1##*.} | tr "[:upper:]" "[:lower:]")  # The extension in lowercase
   spotTest=$(mdls -name "kMDItemKind" -raw "$1" | grep -oE "$mdRegex")  # Contains creating app
   fileTest=$(file "$1" | grep -oE "$mdRegex")  # Same as above. Returns app if present, or null
   if [[ ! -d "$1" ]]  # If item not a directory then process file
      if [[ $extension =~ $extRegex || $spotTest || $fileTest ]]  # If any of the tests is +ve ...
         if [[ ! -d "$destFolder" ]]; then mkdir -p "$destFolder"; fi  # Create folder if missing
         mv -f "$1" "$destFolder"  # Move the file
   shift  # Move the positional parameters along one, e.g., $3 -> $2, $2 -> $1, $1 is wiped
exit 0

Save this file as in any location yo like, but I would suggest a folder referred to on your $PATH. If you really want to use this as an embedded script, delete the shebang (#!), and the lines beginning with until, do, shift and done. To be sure, replace exit 0 with return 0, but you can probably get away without this.

The recipe

    1) Name the Description something like 'Move MS Office files', or something equally descriptive
    2) Set the If test to 'all'
    3) Set the first condition to 'Any File'
    4) Set the second condition to 'Date Last Modified', with 'is not in the last', 2 and 'days'
    5) Under Do the following: set 'Run shell script', change 'embedded script' to 'Other...' and then find and select the above saved script. Optionally, add a Growl notification to show what file has been moved

The script could be altered with different regular expressions for other files, for example if you wanted to move all Creative Suite files to a set folder. But I've had enough of regexs for the time being. You can also change the behaviour to move the files to different subfolders depending on file type, but my fingers hurt and I can't be bothered. (Hint: use a variation on the conditional folder creation in the script above.)
Posts: 1
Joined: Sun Jan 09, 2011 10:09 am

Another option that avoids the use of a shell script is to create a condition "Extension" "matches" [table] where the table is a list of common MS Office extensions.
Posts: 9
Joined: Sat Nov 17, 2018 9:50 pm

Return to Tips & Tricks - DO NOT POST QUESTIONS