Six Colors
Six Colors

by Jason Snell & Dan Moren

This Week's Sponsor

Save 20% on the award-winning Audio Hijack with coupon code 6C20AH!

By Jason Snell

Bad AppleScript: Use Hazel to auto-compress Logic projects

Note: This story has not been updated since 2021.

My office file server still has a lot of free space, but one of these days I’m going to fill it to the brim with old podcast project files. So I’ve been considering what to do to reduce the amount of archival data I’m storing. A while back, Marco Arment told me about his method of dealing with old project files—a shell script that uses the flac command-line utility to losslessly compress the giant uncompressed audio files that take up the bulk of space in any podcast project. The result is almost a 50 percent space savings!

In practical terms, after a few weeks (or in the case of a couple of podcasts I do, a year) I am not likely to need to go back to my original source files again. (And if I do, I’ve got a shell script to decompress all the archived files.) What I wanted to do was create an automated system in which projects would automatically get compressed after a waiting period. Since I store all my files on a Mac mini, I decided to use Noodlesoft’s Hazel to watch my folders and perform the automation using AppleScript.

This ended up being a multi-stage process. First, I needed to set up a Hazel rule that would look at a folder’s age and judge if it’s ready to be archived. This required me to extend Hazel’s functionality via a small script that would check to see if a folder actually contained any Logic projects—and would leave it alone if it didn’t.

This rule set only finds folders modified in the past three months that are not from this year—a weird restriction, but at the end of the calendar year I do an end-of-the-year clip show on The Incomparable, and so I don’t want to bother compressing old projects that are eligible for inclusion in that show. (This way, my Mac mini will have something to do on January 1 every year—namely compressing nine months worth of projects.)

The last item, though, is the tricky addition I needed to make—it runs an embedded AppleScript that looks inside the folder to ensure there’s at least one Logic project inside. That script looks like this:

set theStatus to false

tell application "Finder"
set file_list to entire contents of theFile 
repeat with anItem in file_list
    if kind of anItem is "Logic X Project" then
        set theStatus to true
    end if
end repeat
end tell

return theStatus

If the script returns a status of false, the folder gets passed over. Otherwise my script runs, and the folder’s contents get losslessly compressed. That complete script is here. Here are some highlights:

on hazelProcessFile(theFile)

Hazel requires you to wrap your AppleScript commands in an onhazelProcessFile handler. The target folder is set to the variable theFile.

set theProjectFiles to {}
set thisFile to {}
set theBigScript to ""
tell application "Finder"       
    set file_list to entire contents of theFile
end tell

This block defines some variables (two arrays and a string) and creates a new array, file_list, which contains every single file within the folder (including files in subfolders).

repeat with anItem in file_list
    set thisFile to getPath(anItem)

We’ll repeat through the entire list of files, and first use a subroutine called getPath to process each item. getPath, which I re-use across several scripts, returns the item’s file path (as a string), its filename stripped of all file extensions, and its file extension. This is useful for building commands to be executed via the do shell script command.

if (item 3 of thisFile) contains "logic" then
set end of theProjectFiles to (anItem as alias)

This variable, theProjectFiles, is collecting any Logic project files and adding them to an array. This will let me rename them later. (In a standalone version of the script, the lack of any Logic projects in a folder will cause the entire process to abort, but since Hazel has already verified the presence of a Logic project, I’m not going to worry about it here.)

else if (item 3 of thisFile contains "wav") or 
    (item 3 of thisFile contains "aif") or 
    (item 3 of thisFile contains "aiff") then   
        set theBigScript to (theBigScript & 
        "/usr/local/bin/flac -s -f -V —lax —best —delete-input-file '" & (POSIX path of (anItem as alias)) & "' -o '" & (POSIX path of (item 1 of thisFile)) & (item 2 of thisFile) & "." & (item 3 of thisFile) & ".flac' ; ")
end if

This is the core of the script. If there’s an uncompressed audio file, we add a flac command to the variable theBigScript which will be executed at the end of this process. That command is:

/usr/local/bin/flac -s -f -V —lax —best —delete-input-file input file -o output file

It converts the input file to a FLAC file and deletes the original.

The variable theBigScript is a bunch of individual flac commands chained together via semicolons. Yes, I could just execute a do shell script command right here and save myself time, but for various reasons I need to wait until the end of the process to do them all in one batch, so that’s what I’m doing.

The rest of the sample script is just the renaming of all the Logic project files and the running of the big do shell script command.

Before (right) and after (left).

On a project I chose at random from my archive, the script compressed 11 project files and reduced a 5.72GB project folder to 2.57GB, 45 percent of its original size. On a couple of terabytes full of projects, it adds up fast.

I realize this is a very specific use case, but it’s worth considering how you can use Hazel and whatever scripting language you’re comfortable with to automate tasks on your Mac or, if you’re like me, a Mac server.

How to decompress the folder later? Here is the decompress script, which you should run as a shell script after changing into the directory you want to decompress:


shopt -s nullglob
for w in *.flac */*.flac ; do
    flac -d -f -w —delete-input-file "$w" -o "${w%%.flac}"
    if [ ! $? -eq 0 ] ; then echo "FLAC failed, aborting: $w" ; exit 1 ; fi

for p in *.compressed ; do
    mv "$p" "${p%%.compressed}"

If you appreciate articles like this one, support us by becoming a Six Colors subscriber. Subscribers get access to an exclusive podcast, members-only stories, and a special community.

Search Six Colors