Hazel for removing obsolete backup files?

I recently realised that when you delete a Scrivener project, the backup files for that project remain in the backups folder. This might not be a bad thing, in some ways, in that it might conceivably rescue you when you later realise that something in the deleted project would be useful, but generally I would prefer to get rid of backups that are no longer needed.

This in turn led me to wonder if there was a way of getting Hazel to do it automatically. Has anybody ever tried this? I suppose it would need Hazel to watch the Trash folder, and whenever a .scriv file landed in it, it would go and look for files with associated names in the backups folder. I don’t even know if this is possible, but I thought I would ask, as various people who haunt the forums are much more expert than I.

Cheers, Martin.

Martin, are you essentially asking Hazel to monitor Folder A and if certain conditions are met, make changes in Folder B? I imagine Hazel could do this by triggering an Applescript or Automator routine.


I suppose what I’m asking is whether Hazel can monitor the Trash (which would be Folder A in this case) but also read the name of the Scrivener project when it lands in the Trash, and select the backup files that belong to that project (which ought to have a filename based on the original) and move those to the Trash, as well.

Just trying to describe it makes my head spin.


Try the attached Hazel rule set.

ScrivenerBackupCleaner.hazelrules.zip (2.17 KB)

[b]Caution: This rule is designed to automatically move backups out of your Scrivener backup folder, to another location, if the project they came from is ever found in the Trash. By default it will be inoperative when installed. It will silently fail until proper path locations have been pasted into the indicated areas, below.

Use at your own risk; not official L&L utility; all that jazz.[/b]

To install, follow these steps:

  1. Click the + button in the folder list.
  2. The trash folder is hidden, so use Shift-Cmd-G to manually go to a location, and type in ~/Trash.
  3. Click the Open button.
  4. Import the unzipped Hazel rule set to this folder, using the gear menu below the folder list.
  5. Before activating the rule, double-click on it to edit. Click on the Edit script button toward the bottom.
  6. You will find two all uppercase sections at the top that need to be filled in. The script will not work until you do. In both cases these need to be full paths. You can’t use the UNIX ~ shortcut.
  • backup_folder: this should point to your Scrivener backup location. It’s easiest to get that from the software itself in the Backup preference pane. Just copy and paste that path, replacing the FULL_BACKUP_PATH, and leave the quotes intact.
  • archive_folder: specify a location where the script should move the backups it detects. It would be safer to have them moved to a separate folder where you can periodically remove them (or set up another Hazel rule on that folder to do so once they age). Or, if you prefer to live life on the edge, just set this location to your Trash folder and they will be trashed moments after the parent project is. I would stick with another folder for a while though, as I’ve only tested this a bit on my machine.
  1. Click the Ok button and activate the rule in the list.

I would test by creating a blank project, making a backup of it, and then trashing it.

One limitation of this script is if you create two projects of the same name and trash them both. The OS will automatically call the second “My project copy.scriv”, and the way my script is set up to work, it would then search for “My project copy” in the backup folder, and find nothing since the ‘copy’ not a part of the original name.

Briiliant! Ioa, you are the dog’s whatsits. I’ll play around (sorry – conduct exhaustive scientific testing). It was the hidden nature of the Trash that was the first hurdle to overcome, and I couldn’t think of a way of getting over it. But I’m sure the rest would have been beyond me, too.

With any luck, this will be of use to others, too.

Many thanks again,

I think I’ll use this too.
Ioa, thank you.


Unbridled genius!

Thanks Ioa.

Hmmm. Haven’t got it to work yet. Anyone else have success? The script keeps failing for me. It detects the scriv project in the Trash, but fails after that. It happily created an archive folder when it didn’t exist, so it gets to that point OK.


If you run into any problems, let me know what the project name was. There might need to be some punctuation avoidance. Also check the Hazel logs (there is a handy button in the Info tab).

Hi Ioa,

I’ve been tinkering and tried various things that I thought might work, but so far no joy. The logs are distinctly unenlightening. They merely say:

2013-01-16 21:41:20.212 hazelworker[7674] Test.scriv: Rule Scrivener project locator matched. 2013-01-16 21:41:20.293 hazelworker[7674] [Error] Shell script failed: Error processing shell script on file /Users/martinbb/.Trash/Test.scriv. 2013-01-16 21:41:20.293 hazelworker[7674] Shellscript exited with non-successful status code: 1 2013-01-16 21:41:20.300 hazelworker[7674] Done processing folder Trash

I wondered if it might be something to do with the format of the backup filename, but I haven’t so far found what works. My backups were in the automatically generated format:

My Story.bak2012-10-13T17-14.zip

I thought this might cause a problem, so I changed them to the other automatically generated form:


Still no joy. I did originally have a space in the filename (Test 01.bak.scriv) but even removing that has not resulted in an improvement. I’m sure it’s something simple – I just haven’t worked out what it is yet.

In any case, thanks for the work – and I put a link on the Hazel forums in case anyone should find it useful.

Cheers, Martin.

I did find a punctuation bug (where names like “My project (one).scriv” would fail), which the code below should fix. First off try the revised script below. Even though punctuation isn’t the problem, I did fix another problem with the way filenames are addressed.

#!/usr/bin/ruby -w
require 'fileutils'

# Set this to the full path of your Scrivener backup folder
backup_folder = 'FULL_BACKUP_PATH'

# Set this to the full path where archived backups should be moved
# This can be set to the user trash folder if you wish
archive_folder = 'FULL_ARCHIVE_PATH'

# Create archive folder if it does not exist yet
unless File.exists?(archive_folder)

# Fetch path of matched project in Trash and store the name of it sans the rest of the path
ARGV[0] =~ /([^\/]+)\.scriv/
search_for = $1.gsub(/[\(\)\$\^\{\}\[\]\\\*\+]/, '.')
unless search_for

# Loop through backup folder looking for matching backup names and move them to the archive folder
Dir.new(backup_folder).each do |backup|
	if backup =~ /^#{search_for}\.bak/
		FileUtils.mv(backup_folder + '/' + backup, archive_folder + '/' + backup)

No joy, I’m afraid – it fails with the same error as before. Could there be a permissions problem? I notice that both my Library and Application Support folders are 700, not 755.


Edit: Strike that – I failed to edit the paths :blush:

I’ll try again!

Edit: Hoorah!! Success. Thank you – and I’ll now go and boil my head …

I bet it was just how you named the paths then. The original script assumed they would have a ‘/’ on the end. Glad it works, I’ll update the download as the old one wouldn’t work for anything with parentheses and a few other common punctuation marks.

And thanks for bringing up the idea. This will be useful for myself as well. As someone who makes 30 or 40 test projects per day, it renders the default and safest backup settings useless, unless you want thousands of “test_paragraph_deletion.bak1.zip”!