Efficiency expert needed for delete files loop

I have a script that deletes files older then a certain number of days. The meat of the script is the following loop:


set retention to 7 * days

set cut_off to (current date) - retention
tell application "Finder"
	set file_list to items of folder pdf_folder
	repeat with t_item in file_list
		set file_info to info for alias (t_item as text)
		set created to creation date of the file_info
		if (created < cut_off) then
			move alias (t_item as text) to trash
		end if
	end repeat
	empty trash
end tell

While the script works fine, it is agonizingly slow. It has to scan more then 1000 files and will delete a couple of hundred of them. What ought to be a trivial task takes nearly an hour to complete (one could do it faster manually). Can anyone suggest a more efficient algorithm? TIA.

You can save the following script as an application and then drop your source folder on it to run or you could hard code your source folder. I just tested this on a folder with 1,500 files. It deleted 800 of them in 31 seconds (PB 1.25GHz/10.3). Note that to actually delete the files, you’ll need to uncomment the “do shell script…” line. Please, please, please test on non-essential files first:

Jon


[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

Thanks for the reply. Although this is a scheduled script and can’t be drag & drop, I think I get the idea. You are, for all intents, using Unix rather then Applescript. In otherwords you are cheating (sort of :)).

If pure Applescript is that inefficient, in this instance, that Unix is needed then I am better off writing a Unix script where it indeed is trivial.

I don’t think it’s so much that AppleScript is inefficient - in fact, in many ways it’s quite efficient), but the particulars of how the Finder deletes files is your problem in this case.

For example, the ‘delete’ command actually moves the file to the trash which forces the Finder to update that file’s location on disk, and then you later empty trash, which scans the trash folder and deletes the items within it. So essentially you’re doing twice the work. This isn’t an AppleScript limitation as much as a limitation in the Finder’s delete file implementation.

You’re also doing far more work than you need to in your script. First you get every file in the folder, then you loop through it getting “info for” each file (which forces the Finder to read all the properties of each file), then you check the date and delete the file if necessary. At the very least, you don’t need to get ‘info for’ the files since the Finder can tell you the creation date of a file without having to go through all the other ‘info for’.

A much more straighforward AppleScript implementation would be:

tell application "Finder"
	set files_to_delete to every file of folder "Macintosh HD:path:to:pdf_folder:" whose creation date is less than ((current date) - 7 * days)
	delete files_to_delete
	empty trash
end tell

That said, removing files older than a certain date is a cinch to do in a shell script. This one-liner will do it for you:

do shell script “find /path/to/pdf_folder -mtime +7 -delete”

It also doesn’t have the inherent problem of filenames with spaces and other ‘invalid’ characters which can choke a shell script.

This was actually what I was looking for. I thought there had to be a more efficient way but I couldn’t have come up with that, from my book on Applescript, in a million years. Thanks.

Yep. A simple crontab entry.

One little problem:


set files_to_delete to every file of folder "Macintosh HD:path:to:pdf_folder:" whose creation date is less than ((current date) - 7 * days) 

Produces the error. “Can’t make some data into expected type.”

Which version of the Mac OS are you running?

‘whose’ clauses have been problematic in earlier Finder versions. The above code works on 10.3.1 (and I assume you changed the folder path to a real folder on your machine, right?)

10.2.6

Although ‘assuming’ is dangerous, you are safe in this case. :slight_smile:

The whose clause fails for me too - OS X 10.2.8. :?

– Rob

I can confirm that it does work in 10.3.1.

Jon

Unfortunately, that does not help. It is too soon to upgrade to Panther on our production systems.

Is the 30 seconds it takes to run the script I posted above too slow? (It should work on 10.2 without problems.)

Jon

It is not a matter of time but rather a matter of Unix. My client has an aversion to using Unix. If this is unsolvable in Applescript then I’ll just run a Unix ‘find’ command in CRONTAB.

Um, what? Is the client using OS X? If so, I’m afraid to break the news that he’s using Unix. The script above is AppleScript making some calls to Unix, just like the OS does.

Jon

The following Unix-free script ran on my machine (PB 1.25GHz/10.3.1) checking 1,500 files and deleting 1,000 of them in 38 seconds:

Jon


[This script was automatically tagged for color coded syntax by Convert Script to Markup Code]

Thanks for the replies.

Perhaps I should rephrase that. The client has a aversion to maintaining Unix scripts. They do not want to need a Unix expert to manage/maintain their systems (after I’m gone) and since OS X hides all that stuff they want to keep it that way.

I see what your script is doing but why is it faster then my original code. It appears to be doing essentially the same amout of looping except it is outside the ‘tell’ block.

Precisely because it is outside the tell block of the Finder. The Finder is painfully slow when scripting is involved (and it always has been). Also, using “list folder” and having only one move command makes it much faster as well. I’m a little confused. If someone is savvy enough to be able to maintain the pure AppleScript code, then they should be able to maintain the shell scripts embedded within it. A few simple comments would suffice. Still, 7 seconds longer for the vanilla AS version isn’t too bad.

Jon

Thanks for the explanation. I guess I am handicapped trying to learn Applescript from the books I have. No where was it clear what can be done outside the ‘tell’. It implied that all file manipulations were done by ‘Finder’. At least anything they did with files was in ‘Finder’.

Be careful with your assumptions. :slight_smile:
Remember, the customer may not always be right but the customer is always the customer.