Smart Trash Emptier

Being very much a noob, I was hoping for some advice about the best way to execute the following concept. I would like to create a script that deletes elements in the trash starting with the oldest to maintain a given amount of free drive space. Optionally, there could be a certain amount of hysteresis in the system so it wouldn’t always be on the edge of deleting files (ie when space falls below LO_LIMIT, delete files until space is above HI_LIMIT). Files newer than a certain amount could require confirmation, although Time Machine removes a lot of the motivation for this.

Am I right in assuming that emptying the trash is an all or nothing affair, or is there a way to “empty” individual items? I also need a way to determine what items have been in the trash the longest. Thanks for any insights.

Well this isn’t so hard but you say you’re a noob so it’s maybe a challenge.

First of all you’ll need a action after something is added to a Folder, the trash is a folder named ‘.Trash’ in your user directory. The easiest way is using folder action scripts.

Then you want some sort of FIFO directory. So you need to keep track when the file is added. The nice thing is that a user can’t change the access time of the file when it is in the trash. So without changing the modification or creation date we can use the access time. So when a file is added to a folder we update the access time to the current date with touch.

Then when the Trash folder size becomes too large we pick the oldest file of the folder with ls -cut | tail -1 and delete it with rm. Then check the trash again and repeat this process till you’re over the minimum size. ls -cut lists directory contents and -cut will sort it on it’s access time. Then we’ll pipe it to tail -1 to get only the last file which should be the file that is placed first in the folder, it is the oldest file of that folder.

All these action I recommend to use when a file(s) is added to the folder. idle handlers or intervals aren’t so handy in my opinion. This way your trash is up-to-date and also when the user doesn’t put any files in the trash for a few days the script won’t run unnecessarily.

Things are more flexible than I’d feared. Thank you so much for the info! :smiley:

I elected to change the modified date so I could interface with Applescript more easily. I also scheduled it to run every hour via cron as adding files to the trash isn’t really the trigger I need. Here they are in case anyone wants them. Thanks again for your help.

The folder action script (for the trash folder):

on adding folder items to this_folder after receiving added_items
	try
		repeat with this_Item in added_items
			tell application "Finder"
				set modification date of this_Item to (current date)
			end tell
		end repeat
	end try
end adding folder items to

The script to delete files:

property LO_LIMIT : 50000 -- size (in MB) to start deleting files to make room
property HI_LIMIT : 60000 -- size (in MB) to stop deleting files to make room

tell application "Finder"
	
	-- see if space below low threshold
	set freeSpace to (the (free space of startup disk) / 1024 / 1024)
	
	if freeSpace < LO_LIMIT then
		
		-- get items in trash sorted by modification date
		set theItems to (sort every item of trash by modification date)
		
		repeat with index from (count of theItems) to 1 by -1
			
			-- delete next oldest item 
			set this_Item to item index of theItems
			set posixPath to POSIX path of (this_Item as string) as string
			set rm_command to "rm -r \"" & posixPath & "\""
			
			do shell script rm_command
			
			-- see if enough space has been cleared
			set freeSpace to (the (free space of startup disk) / 1024 / 1024)
			if freeSpace ≥ HI_LIMIT then
				exit repeat
			end if
			
		end repeat
	end if
end tell

Also created this one to delete a certain amount of oldest files for times when I need to ask for more space manually (as opposed to just emptying the whole trash).

property AMOUNT_TO_FREE : 10000 -- amount (in MB) of files to delete

tell application "Finder"
	
	-- get current free space
	set initialfreeSpace to (the (free space of startup disk) / 1024 / 1024)
	
	-- get items in trash sorted by modification date
	set theItems to (sort every item of trash by modification date)
	
	repeat with index from (count of theItems) to 1 by -1
		
		-- delete next oldest item 
		set this_Item to item index of theItems
		set posixPath to POSIX path of (this_Item as string) as string
		set rm_command to "rm -r \"" & posixPath & "\""
		
		do shell script rm_command
		
		-- see if enough space has been cleared
		set freeSpace to (the (free space of startup disk) / 1024 / 1024)
		
		if freeSpace ≥ initialfreeSpace + AMOUNT_TO_FREE then
			exit repeat
		end if
		
	end repeat
end tell

Emptying the trash is apparently a nervous twitch of mine; it’s proving quite difficult to avoid it! :slight_smile: