make your own Trash Watcher utility

Trash watcher 2

So twice in the last couple of weeks, I’ve found that something funny has been going on with Xcode, source control and Dropbox. The weird behaviour is that both times a whole load of my Xcode projects got moved to the Trash without my knowledge or permission. Fortunately, I noticed in both cases, and while I haven’t got to the bottom of the problem yet, I thought the first thing I’d better do is a bit of defensive scripting!

With that in mind, I created this little Trash Watcher utility to warn me anytime something is moved to the Trash. It’s quick and easy to make, and you can customise it to do various other things apart from give a warning if you like (for example, you could make it delete files of a certain kind, size or date automatically).

Start by opening the AppleScript editor (or Script Editor on 10.10), and paste the following lines into it:


on adding folder items to this_folder after receiving added_items

set listOfFiles to {}
repeat with i from 1 to the count of added_items
set a_file to item i of added_items as text
set stripTrashPath to offset of "Trash" in a_file
set a_file to text (stripTrashPath + 6) thru -1 of a_file
set a_file to a_file & "
"
set end of listOfFiles to a_file
end repeat

display dialog "The following items were moved to Trash: " & return & return & listOfFiles buttons {"OK", "View"} default button "View" cancel button {"OK"} with title "Trash Alert" with icon 0
set btn to button returned of the result
if (btn = "View") then
tell application "Finder" to open the trash
end if
end adding folder items to

 

Here’s what the code does. The first and last lines define a Folder actions handler, where the variables ‘this_folder’ and ‘added_items’ will be replaced by the name of the folder you attach this script too (we’ll do that in a minute), namely the Trash folder, and the items that have been moved to the Trash.

The next line, declares an empty list, so that we can populate it later with just the names of the items, rather than their full path adddress.

Then comes the repeat block. This first determines how many items there are to be added and then iterates over them, applying the five ‘set’ commands on each file. Those five commands are all doing one thing: stripping the path from the item name down to just the item name itself so that we can display it nicely in the display dialog command that follows.

Note that the display dialog command adds a couple of buttons, and collects the result as to which button you pressed. Notice that “OK” (typically an action button) is used to dismiss or cancel the dialog. “View” opens the Trash folder in the event that you want to check or remove the items that have been added.

With the Script editor active, make sure your script compiles by pressing ‘Command-K’, but don’t try to run it yet. We need to attach save the script in the right place first, and then attach it to the Trash folder.

With Script editor still active, press ‘Command-S’ to bring up the ‘Save’ dialog box. Give it a descriptive name like ‘TrashWatcher.scpt’ or similar. Do not click ‘Save’, but instead press, ‘Command-Shif-G’ on your keyboard and enter this location into the box that pops up:

~/Library

and click ‘Go’. In the resulting window, scroll down to the Scripts folder and look inside it. If there is already a folder called ‘Folder Action Scripts’ then save the script in there. If not, click ‘New Folder’ in the bottom left of the window, and create a ‘Folder Action Scripts’ folder (be sure to get the name exactly right).

With the script saved in ~/Library/Scripts/Folder Action Scripts/, right click on any folder in a Finder window and choose ‘Services > Folder Action Setup’ from the contextual menu.

Folder Actions Setup

This will open a new dialog box with a list of scripts to choose from. Choose the TrashWatcher.scpt (or whatever you happened to call it) and click “Attach”. In the remaining panel, make sure the Trash folder is selected and no other.

That’s pretty much it; your TrashWatcher folder is set up, so move something to the Trash and make sure it fires. Everything OK? Hmm, maybe, but we need a few refinements. For one thing, every now and again OS X will move the .DS_Store files to the Trash, and we don’t want to know about these. Also, it would be good if the file name actually indicated whether it was file or a folder that was being moved. In fact, it does so already (Folders are indicated by a colon), but it would perhaps be clearer and more orthodox if folders were followed by a forward slash, as they are usually indicated that way in path names. To achieve both of these, refine the script above to look as follows, remembering to compile, save and test it (by moving something to the Trash, not from running in the Script Editor).


final script

Finally, with a bit of imagination and experimentation, you could add various other conditions to this script. For example, you could have it immediately delete files that are of a certain size or certain kind as soon as they are placed in the trash (tip: you’ll need to use Finder’s “empty the Trash” command after testing each file for whatever criterion you want to use). I’ll leave those as exercises for the reader, but feel free to post your scripts in the comments if you’re particularly pleased with some variation you’ve come up with!

Happy Scripting!

Advertisement

About philastokes

Independent Software Developer, Technical Writer and Researcher at SentinelOne. Explaining the unexplainable with images, video and text. Scripting anything imaginable in AppleScript, Bash, Python and Swift.

Posted on October 13, 2014, in AppleScript, Folder Actions and tagged , , . Bookmark the permalink. 11 Comments.

  1. Alaric Calmette

    Hi!
    I’d like to watch only for a specific file. How can i do it?
    Also the attach workflow you gave isn’t available anymore… I would like to automatically run and attach the script when a script is ran. Is that possible?

    • Sorry, I didn’t realize that link had gone down. I’ve fixed it now.

      I’m not sure what you mean by “automatically run and attach the script when a script is ran”.

      If you can give me a few more details, specific example or use case, I should be able to give you a better answer.

      • Alaric Calmette

        First thanks for your quick answer!
        Here are the detailsI:
        have an app that is just a shell script bundled in an app. When the user launch the app it installs and run a daemon. I’d like to create a script that watch the event ” ‘myApp’ was moved to trash ” so i can launch a stop and uninstall script.
        Also it would be better if the script kind of attached itself to the Application folder instead of requiring a user action.

        • Detecting a particular file or folder name is fairly straightforward. Just change “myappsname” to whatever is the name of what you’re looking for.

          on adding folder items to this_folder after receiving added_items

          set listOfFiles to {}
          repeat with i from 1 to the count of added_items

          set a_file to item i of added_items as text
          set stripTrashPath to offset of "Trash" in a_file
          set a_file to text (stripTrashPath + 6) thru -1 of a_file
          end repeat

          if a_file contains "myappsname" then
          display dialog "Stop!"
          end if

          end adding folder items to

          I’m not quite sure what you want to happen next when you say “it would be better if the script kind of attached itself to the Application folder…”.

          You could have the script automatically move the app back OUT of the Trash and back into the Applications folder, if that’s what you mean (remember this action only gets triggered when the file in question has already been added to the Trash, so probably want you want to do is reverse it!).

          • Alaric Calmette

            What i would like to happen next is this :

            I want my script to be attached to the application folder (i.e. watch the on remove folder items to this_folder event for the Applications folder) without having to to all the workfow.
            In other words is it possible to script also the workflow of the attach process?

          • Hmm, well, you can’t prevent an action before it happens with Folder Actions, so either way you have to wait for the move to happen before it’ll get triggered.

            Why not just lock down the permissions on your Applications folder so that files can’t be moved out of it without a password? That would seem an easier solution.

          • Alaric Calmette

            I was unclear.
            Everything i made, my app the script files… will be bundled for the end user.
            When the user double click on myapp.app, it launches two scripts : one for installing the daemon, one for launching this daemon.
            Once it’s done, the user has no way to uninstall the daemon simply.
            So what i would like to do is Attach my uninstall.scpt with the Applications folder so when the end user drag myapp.app from Applications to trash, my uninstall.scpt is triggered and the daemon is killed and destroyed.
            But i want to automatise the attachment process. I don’t want the user to do it manually.
            I want that when the user double click on myapp.app, the uninstall.scpt is attached to Applications/ .

          • Oh, I see.

            Right, a couple of things.

            1. An app can’t attach any kind of actions to a user’s folder (for very good security reasons).

            2. Your app needs to have an ‘uninstall’ function, a button or menu option which basically uninstalls the daemon and then on success tells the user to drag the app to the Trash.

            3. I could wrap your script in a Cocoa bundle with an interface that would allow the user to make choices like uninstall, run or whatever else your script does. But…that’s commercial work that I charge for. The free advice I give out here on the blog is only intended for end users, not fellow developers. Sorry! 😎

            If you want me to help you develop your app, contact me via email and we can talk terms!

            HTH! 🙂

          • Alaric Calmette

            Okay! I was affraid it was impossible to do so. And for the cocoa bundle i’ll try to figure it out myself 🙂 but tjhanks anyway!

  2. No. I did eventually track down my problem as related to Xcode and Source Control.

    Dropbox, however, is an an app I’ve since happily trashed.

    My recent communications with them have left a very sour taste, and aside from their dismissive attitude to customer service, I simply don’t trust the changes they’re making to users’ macs behind the scenes and without either notification or permission.

  3. Could your unexpected trashing of data possibly due to this below?

    In the early days of Dropbox, I got in touch with them to complain about a particular behavior that they ended calling a “feature”: The catastrophic way Dropbox dealt with deletion of Symbolic Links.

    Below the details… (they may have changed Dropbox since then but I can’t tell because I gave up on it, this was just too bad!).

    If I put a Symbolic Link in Dropbox, and then delete it, the linked data would be deleted! – and actually even if not located in Dropbox.

    This is a dangerous behavior totally different from that of the Finder, could be fine for expert users, but should be banned for a software destined to the general public.
    It’s not that the general public will likely play with symlinks, but some common apps do – like DevonThink that uses symlinks behind the scenes when the user casually links some external content in a document.
    When I deleted such a DevonThink document in Dropbox, the data that it linked to would be deleted as well, and potentially that could even be an entire drive!
    I pointed this scenario to them and their only reply was that existing users who got used to this “feature” would be upset if they removed it.

    So regarding the mysterious trashing of some data related to Dropbox, could it have something to do with symbolic links somewhere? And it could be indirectly… It wasn’t obvious in the case of those DevonThink documents, because what looked like a simple document to the user was actually a package that contained those Symbolic links, unseen to the user. And trashing what looked like a simple document ended up deleting linked data out of the blue…

%d bloggers like this: