Automating backup of Flash drives Creative Commons License

posted in the wee hours by Constantinos. Filed under Code, OS X

This post was originally published in 2007
The tips and techniques explained may be outdated.

I have a lot of my critical work on a few flash drives which I carry around with me constantly, mainly because I work on a number of machines and would like to have a central repository of my work. After losing one of the drives recently though (bound to happen sooner or later), I looked further into automating the backup process (I had lost about 2 days of work). That’s when I stumbled accross this hint on macosxhints.com, but the script didn’t exactly fulfil what I had imagined my automated process to do.

Ideally, the automated backup process would have these features:

  1. Not require installation of any third party app
  2. Have the ability to somewhat customize the backup script for each thumb drive
  3. Have the backup script silently run whenever the thumb drive is mounted
  4. Require little to no set up for each new thumb drive that I want to backup
  5. Support spaces in Volume names
  6. Not try to backup the boot drive under any circumstances (don’t ask…)

Updated 2007-03-10: I updated the backup script to include automated handling of archives, and keeps an arbitrary number (specified in the preferences of the script) of incremental archives using rsync's --link-dest parameter, as recommended by John in the comments. This creates what functionally amounts to FULL backups, but with a fraction of the space needed for an actual tar backup. Also it can be configured to keep at most one backup per day, or with minor editing at most one backup for any period of time.

Updated 2007-03-18: I've created a second script which can be used as a drag-n-drop solution. Simply save the script as an application bundle, save it somewhere handy, and drag it to your dock. Now you can drag your thumb drive on the script which will perform the backup, and then eject your drive!

Updated 2008-03-10: Folder action modified to work with Leopard. Well, more like hacked at this point, but it seems to work.


Now to satisfy the first parameter, using Do Something When was out of the question, even though it seems like a good piece of software. That’s when I turned to Fodler Actions, and found this hint again on macosxhints.com. I then proceeded to read the Apple-published Folder Action for automating backups (which, again, didn’t do quite what I wanted), so I came up with this:

A folder action that scans the root folder of the mounted volume, and looks for (one of) a specified file name.

property backup_script : "rsync.app" (* add/change this string to match the name of your script *)
 
on adding folder items to this_folder after receiving these_volumes
    tell application "Finder"
        try
            set the volume_list to every file of this_folder
 
            (* go through all entries in /Volumes/ *)
            repeat with i from 1 to number of items in volume_list
                set this_item to the original item of item i of volume_list
                if the kind of this_item is "Volume" then
                    set this_disk to (this_item as alias)
 
                    (* is this item the newly mounted disk? *)
                    if this_disk is in these_volumes then
 
                        (* iterate through all files in the root of disk *)
                        set searchCmd to "ls -d " & quoted form of POSIX path of this_disk & backup_script
                        (* check to see if a backup script is available *)
                        set searchResult to ""
                        try
                            set searchResult to do shell script searchCmd
                        end try
                        (* run the backup script *)
                        if (searchResult starts with "/Volumes") then
                            set backupFile to POSIX file searchResult as alias
                            open backupFile
                        end if
 
                    end if
                end if
            end repeat
        on error error_message number error_number
            if the error_number is not -128 then
                display dialog error_message buttons {"OK"} default button 1
            end if
        end try
    end tell
end adding folder items to

Download this script

If you already know how to apply folder actions, just save the script above and apply it as a folder action to the /Volumes/ folder. If you don’t know (or don’t remember) how to do that, re-iterating the instructions from this Apple page, follow these steps to do it:

  1. Copy the above code in Script Editor
  2. Save it as a script in /Library/Scripts/Folder Action Scripts/, and give it a descriptive name
  3. In Finder, click Go -> Go to Folder (or just press cmd-shift-G), and type /Volumes/.
  4. Launch the Folder Actions Setup utility (probably located in /Applications/Apple Script/ folder)
  5. Click the Add Folder Action (round plus) button at the bottom left
  6. Drag the small folder icon from the Finder window title bar into the Choose Folder sheet dialog, and click ok.
  7. From the dialog that comes up, chose the script you just saved.
  8. You’re done.

Alternatively (or additionally), you can save this script as an application bundle, save it somewhere handy, and drag it to your dock. When you drag a thumb drive on this application the backup process will start, and as soon as it's done the drive will eject.

property backup_script : "rsync" (* add/change this to match the name of your script *)
 
on open dropped_item
    set this_vol_alias to (dropped_item as alias)
    try
        tell application "Finder"
            if the kind of this_vol_alias is "Volume" then
                set the file_list to every file of this_vol_alias
                repeat with j from 1 to number of items in file_list
                    (* check to see if a backup script is available *)
                    set this_file to name of item j of file_list
                    if this_file is equal to (backup_script & ".app") then
                        open item j of file_list (* run the backup script *)
                    end if
                end repeat
            else
                display alert "This script can only be executed on volumes"
                return
            end if
        end tell
 
        delay 2 (* give some time for the backup script to actually launch *)
        tell application "Finder"
            try
                set bakapp to creator type of process backup_script
                repeat while bakapp is not equal to ""
                    delay 1 (* the backup is still running, we can check again in a second *)
                    set bakapp to creator type of process backup_script
                end repeat
            on error
                if (ejectable of this_vol_alias is true) then
                    (* display alert POSIX path of dropped_item *)
                    eject this_vol_alias
                end if
            end try
        end tell
 
    on error error_message number error_number
        if the error_number is not -128 then
            display dialog error_message buttons {"OK"} default button 1
        end if
    end try
end open

Download this script

Now, for the modified backup script. The properties at the top can be modified on a per copy basis to customize the function of the script.

property archive_backup : true
property number_of_archives : 3 (* 0 for unlimited *)
property with_administrator_privileges : false
property one_archive_per_day : true
 
property display_notification : false
property backup_target : "Backups/" (* MUST be a folder location with trailing slash! Always relative to home folder *)
 
property rsync_params : "-aEz --delete-excluded"
(* END OF PREFERENCES *)
 
set WhereImRunningFrom to path to me
tell application "Finder"
    (* can't run from the script editor *)
    set AppCreator to creator type of WhereImRunningFrom
    if AppCreator is "ToyS" then
        activate of me
        beep
        display alert "This script cannot run directly from ScriptEditor"
        return
    end if
 
    (* NEVER run from the hard drive! *)
    set bootVolume to name of disk of home (* safety feature! *)
    set NameOfDisk to name of disk of WhereImRunningFrom
    if NameOfDisk is bootVolume then
        beep
        display alert "Should not run this script from the boot volume!"
        return
    end if
 
    (* setup backup dir *)
    set homeDir to path to home folder from user domain
    set backup_folder to POSIX path of homeDir & backup_target
    try
        (* quick and dirty check to see if folder exists - must be a good way to do this in applescript? *)
        do shell script "cd " & backup_folder
    on error
        try
            do shell script "mkdir " & backup_folder
        on error
            display alert "There was an error creating the backup folder " & backup_folder
            return
        end try
    end try
 
    (* find source and target *)
    set backupBase to NameOfDisk & "-Backup"
    set targetDir to backup_folder & quoted form of backupBase
    set sourceDir to quoted form of ("/Volumes/" & NameOfDisk & "/")
 
    (* set up archive filename *)
    if archive_backup then
        set thedate to current date
        set theday to day of thedate
        set themonth to month of thedate
        set theyear to year of thedate
        set thetime to time of thedate
 
        set thedate to "-" & theyear & "-" & shortMonth(themonth) of me & "-" & theday as string
        if not one_archive_per_day then set thedate to thedate & "-" & thetime as string
 
        set backupFolder to quoted form of (backup_folder & backupBase & thedate  & "/")
    end if
end tell
 
(* do the backup *)
(* try *)
if with_administrator_privileges then
    set excluded to " "
else
    set excluded to " --exclude='.Trash*' --exclude='.Spotlight*'  "
end if
 
if archive_backup then
    set posixDir to POSIX file backup_folder
    set fileList to list folder posixDir
    set archiveList to {}
    tell application "Finder"
        (* Search for existing backups *)
        repeat with i from 1 to number of items in fileList
            set thisFile to item i of fileList
            set filePath to path to resource thisFile in bundle posixDir
            if thisFile starts with backupBase then
                set archiveList to archiveList & POSIX path of filePath
            end if
        end repeat
    end tell
 
    (* List existing backups in order of last modified date *)
    set latestArchive to ""
    set linkDest to ""
    set listString to ""
    repeat with x from 1 to number of items in archiveList
        set listString to listString & " " & quoted form of item x of archiveList
    end repeat
    set newString to do shell script "ls -dt " & listString (* sort files by modified date *)
    set theList to (paragraphs of newString)
 
    (* Clear out outdated backups *)
    if (number of items in theList is greater than number_of_archives) and (number_of_archives is greater than 0) then
        repeat with y from (number_of_archives + 1) to (number of items in theList)
            do shell script "rm -Rf " & quoted form of item y of theList
        end repeat
    end if
    if number of items in theList is greater than 0 then
        set latestArchive to quoted form of item 1 of theList
        if latestArchive is equal to backupFolder then
            (* Preserve same target folder *)
            if number of items in theList is greater than 1 then
                set latestArchive to quoted form of item 2 of theList
            else
                set latestArchive to ""
            end if
        end if
    end if
 
    if latestArchive is not equal to "" then
        set linkDest to " --link-dest=" & latestArchive
    end if
    set theScript to "rsync " & rsync_params & linkDest & excluded & sourceDir & " " & backupFolder & "; touch " & backupFolder
else
    set theScript to "rsync " & rsync_params & excluded & sourceDir & " " & targetDir & "; touch " & targetDir
end if
 
if with_administrator_privileges then
    do shell script theScript with administrator privileges
else
    do shell script theScript
end if
 
activate of me
beep
if display_notification then display alert NameOfDisk & " drive backed up"
(*
on error
    display alert "There was an error backing up " & NameOfDisk
end try
*)
 
 
to shortMonth(themonth)
    set MonthList to {January, February, March, April, May, June, July, August, September, October, November, December}
    set mm to 1
    repeat until item mm of MonthList = themonth
        copy mm + 1 to mm
    end repeat
    if mm < 10 then copy "0" & mm to mm
    return mm
end shortMonth

Download this script

Copy the above code in Script Editor, and save it as an Application bundle giving it the name "rsync". If you wish to give it a different name, or maintain a number of copies each with a different name, make sure to modify the first line of the Folder Action script appropriately.

Finally, I can just drop a copy of the rsync application bundle in any thumb drive I want to keep a backup of, and apply the Folder Action to any computer I want to maintain backups on. Since the backup script is using rsync for the backup, I can have multiple backups on any number of computers and they will all mirror the contents of the thumb drive whenever the thumb drive is mounted on them. Additionally, a tar-gzipped copy of the thumb drive can optionally be created with a date stamp for archiving. Deletion of old archives must be managed manually.

If you are having permission issues with some of the files on one of your thumb drives, you can enable the with_administrator_privileges property in the backup script. This will cause the script to ask you for a password every time the thumb drive is mounted before performing the backup, but will perform the backup as an administrator eliminating any permission issues.

I feel that this script can still be improved, but for now it works just fine for my needs. If you have any suggestions for improving this process, feel free to add them in the comments.

78 Responses to “Automating backup of Flash drives”

  1. 1. Comment by obiwan
    on 9 Mar 2007 @ 4:35 am

    Maybe try rsync with the ‘-E’ option in order to backup any resource forks also…

  2. 2. Comment by Martin
    on 9 Mar 2007 @ 4:18 pm

    Obiwan, good idea on the -E option.

    Author, works great, until any subsequent time I plug in my flash-drive. Then, I only get an error “There was error backing up VOLUMENAME”. I can’t figure it out. Any ideas?

  3. 3. Comment by Martin
    on 9 Mar 2007 @ 4:20 pm

    Sadly, it looks like the -E that was causing the problem.

  4. 4. Comment by Constantinos
    on 9 Mar 2007 @ 4:29 pm

    Well, I tried both options, and saw no difference in the way rsync handled my files so I don’t know about that… I’m using OS X 10.4.8, with rsync 2.6.9 (installed via MacPorts):

    % rsync --version
    rsync  version 2.6.9  protocol version 29
    Copyright (C) 1996-2006 by Andrew Tridgell, Wayne Davison, and others.
    <http://rsync.samba.org/>
    Capabilities: 64-bit files, socketpairs, hard links, symlinks, batchfiles,
                  inplace, IPv6, 32-bit system inums, 64-bit internal inums
    
    rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you
    are welcome to redistribute it under certain conditions.  See the GNU
    General Public Licence for details.
    

  5. 5. Comment by John
    on 10 Mar 2007 @ 9:18 pm

    This is great! Would be LOADS better though, if it did the Backup on the eject, instead of the mount. Is this possible?

  6. 6. Comment by Constantinos
    on 10 Mar 2007 @ 9:34 pm

    It’s not possible the way this is set up, since when the drive is ejected the script won’t get called until the drive is inaccessible…

    But even if it was possible, there are down sides to that: If you modified a lot of files (let’s say you added a 1Gb file on the thumb drive) do you really want to wait until rsync is done before you can eject ur drive and leave?

    Remember, the backup application lives inside your thumb drive, so you can initiate a manual backup whenever u want…

    As a side note, I’m working on automating archive management as well, so if you want you can have the script automatically maintain the 2 most recent archive copies and delete the rest 🙂

  7. 7. Comment by John
    on 11 Mar 2007 @ 12:30 am

    re:
    > I’m working on automating archive management as well, so
    > if you want you can have the script automatically maintain
    > the 2 most recent archive copies and delete the rest

    Better yet, look into using rsync and hardlinks to create a TimeMachine-esk history of backups. I’ve done this before and it works really well. Check this out: http://www.mikerubel.org/computers/rsync_snapshots/
    or was this what you had in mind?

  8. 8. Comment by Constantinos
    on 11 Mar 2007 @ 12:57 am

    Outstanding! That’s a good idea, instead of having to tar -czf 2 gigs of data every time a backup is required… Since I’ve already written the code to handle arbitrary filenames for backups as well as order them by their last modified time, i can easily use this to cut down on the archive time…

    Thanks!

  9. 9. Comment by Constantinos
    on 11 Mar 2007 @ 3:03 am

    To anyone following this thread: the backup script has been updated, and now automatically handles incremental archives via rsync’s --link-dest parameter. Thanks John!

  10. 10. Comment by Daniel M
    on 15 Mar 2007 @ 2:02 pm

    You can check if a directory exists by using:
    if exists (foldertocheck)

  11. 11. Comment by draftermath
    on 16 Mar 2007 @ 9:28 pm

    my girlfriend always says if she looses her thumb drive she’s screwed. is there anyway to do this in windows?

  12. 12. Comment by yukonquest
    on 17 Mar 2007 @ 12:33 am

    For a Windows solution – I use Streamload (www.mediamax.com). There is a synch option on the site, I have set up synchs for all my thumb drives. At the end of the night, I insert my thumb drive in the my desktop system, and click ‘Synch’. The next morning, I grab the thumb drive and go. The next time I will be away from the system for a while, I insert a different thumb drive and do the same thing.

  13. 13. Pingback by Automatically back up your thumb drive at SoftSaurus
    on 10 Apr 2007 @ 3:04 am

    […] and it’d be great to see a similar solution for Windows. Any ideas? — Adam Pash Automating backup of Flash drives [Voodoo Programming via […]

  14. 14. Pingback by Gnubb’s Blog » Blog Archive » Backing up my flash drive or Floder Actions Are Awesome!
    on 10 Apr 2007 @ 8:03 pm

    […] Voodoo Programming — Backing up Flash Drives Automatically […]

  15. 15. Comment by jason
    on 24 May 2007 @ 7:02 am

    for windows users, checkout the “new” tool from Microsoft. It’s command line, it’s pretty good and it’s free. It’s called robosync. It took a little to get it setup, but I have a shortcut on my desktop, it will copy all my thumbdrive files to a preset location. If files are moved, changed or deleted, the backup is changed too. Works pretty well. I found this thread trying to figure out a way to do something similar on the mac with unix scripting.

    Thanks for the info.
    J-

  16. 16. Comment by Brian Topping
    on 14 Aug 2007 @ 3:47 am

    I ran across your post while looking for a similar solution. In my work, I need a portable file system that is extremely fast and extremely portable for Java development. My build environment writes thousands of files to the directory at a time, and this can happen dozens of times per day.

    One of the issues is that flash has a MTBF for writing that would easily be exceeded by simply storing the files on a thumb drive and working from it. It might work well for someone that saves a few times an hour, but clearly this doesn’t work for someone that creates and deletes thousands of files per hour.

    What I’d like to find is a way to create a RAM disk from my flash drive every time I plug it in, then flush the RAM disk back to flash when I eject it in preparation to take it out. Anyone know of such an animal?

  17. 17. Comment by Mason
    on 6 Sep 2007 @ 1:57 pm

    There is a volume that seems to be related to iDisk that prevented your folder action from working (the volume name is the same as my .Mac account, and has all the contents of my iDisk. Possibly because I have the offline sync enabled?). When I would mount the USB drive, I would get these errors:

    1. ‘Finder got an error: Can’t get kind of item “foo”.’ (where foo is the name of the iDisk-related volume).
    2. A second pop-up: ‘Finder is busy’ with “Edit” and “OK” buttons.

    I made the following change to the folder action, which seems to be working as expected:

    1a2
    > property ignore_volumes : {“foo”, “iDisk” , “WinXP”} (* add/change this list to match the name(s) of volumes you want to ignore *)
    9a11
    > if the name of item i of the volume_list is not in ignore_volumes then
    28a31
    > end if

    I added my iDisk, iDisk-related and Bootcamp Volumes to the ignore_volumes list, and now everything works great. Of course, if you happen to know how to just silently ignore volumes with an unknown type, that would be even better.

    Finally, instead of backing up the full USB drive, I only backup the contents of my 2GB encrypted disk image. The folder action works just as expected.

  18. 18. Comment by Mark
    on 25 Sep 2007 @ 3:14 pm

    Is there a way to do this in reverse?

    i.e. So that when I mount my flash drive it executes an automatic backup of a specific folder or specific folders from my hard drive onto the flash drive?

  19. 19. Comment by Jeetlo
    on 1 Oct 2007 @ 9:41 am

    Great! that’s good idea!

  20. 20. Comment by Constantinos
    on 1 Oct 2007 @ 11:40 am

    [quote comment=”2066″]Is there a way to do this in reverse?

    i.e. So that when I mount my flash drive it executes an automatic backup of a specific folder or specific folders from my hard drive onto the flash drive?[/quote]

    Shouldn’t be too hard… The folder action would stay the same, and the main script would change so that sourceDir would become targetDir, and targetDir would become a (static) sourceDir. Then delete the logic for determining a unique target (or, in this case, source) directory, and it should work as planned…

    Make sure you have backups of everything first 🙂

  21. 21. Comment by Mark
    on 10 Oct 2007 @ 5:52 pm

    Thanks Constantinos! I will give it a try!

  22. 22. Comment by Martin
    on 3 Nov 2007 @ 9:50 am

    In 10.5, the rsync script on the thumbdrive works when you double-click it, but it seems to no longer work auotmatically when its inserted. My Folder Actions are enabled and I have verified that I do have the same script I had working for 10.4 attached to /Volumes. Incidentally, the Folder Action Utility now shows /Volumes in red, does this mean we can no longer attach scripts there?

  23. 23. Comment by Tom
    on 4 Nov 2007 @ 2:41 pm

    10.5 doesn’t seem to support the “received these_volumes” thingie. No idea why. The page on the Apple website with the example code has been pulled as well. However, this seems to work for me:

    property backup_scripts : {"rsync.app"} (* add/change this list to match the name(s) of your script(s) *)
     
    on adding folder items to this_folder after receiving added_items
        tell application "Finder"
            try
                set the volume_list to every file of this_folder
                (* go through all entries in /Volumes/ *)
                repeat with i from 1 to number of items in volume_list
                    set this_item to the original item of item i of volume_list
                    if the kind of this_item is "Volume" then
                        set this_disk to (this_item as alias)
     
                        (* is this item the newly mounted disk? *)
                        if this_disk is in added_items then
     
                            (* iterate through all files in the root of disk *)
                            set the file_list to every file of this_disk
                            repeat with j from 1 to number of items in file_list
     
                                (* check to see if a backup script is available *)
                                set this_file to name of item j of file_list
                                if this_file is in backup_scripts then
                                    open item j of file_list (* run the backup script *)
                                end if
                            end repeat
                        end if
                    end if
                end repeat
            on error error_message number error_number
                if the error_number is not -128 then
                    display dialog error_message buttons {"OK"} default button 1
                end if
            end try
        end tell
    end adding folder items to

  24. 24. Comment by Mike
    on 7 Nov 2007 @ 7:53 pm

    I’m trying to get an rsync backup to work kindof in the reverse of this script. Essentially, a cron-executed AppleScript that does a nightly backup to an external firewire drive. The problem I’m having is with –link-dest not working… it doesn’t create hard links from the old backup to the new one, and instead performs a full backup.

    The rsync command generated by the AppleScript looks like this example:

    rsync -rlptgDH --delete --link-dest=/Volumes/BackupTest/Backup-20071106/bTest/ ~/Desktop/bTest/ /Volumes/BackupTest/Backup-20071107/bTest/

    where “bTest” is the folder being backed up, and the dated folders are created to hold each day’s incrementals. (For testing purposes, I have a small folder “bTest” on my Desktop, and have created a small disk image named “BackupTest” to backup to.)

    For some reason, --link-dest doesn’t like the fact that the folder to compare and the source reside on two different volumes, but it works okay in the script on this page, albeit in the reverse.

    What am I doing wrong?

  25. 25. Comment by Constantinos
    on 7 Nov 2007 @ 8:53 pm

    I think your problem is the H parameter… preserve hard links. If there’s a hard link to a file on a different volume you don’t want to just create a hard link to the file on the different volume, you want to copy it completely at least once. –link-dest will take care of creating hard links in the duplicate backups if the file hasn’t been modified.

    Another parameter you could add is x, though it’s probably unnecessary in your case, but you might run into other problems if the directory being backed up has links to files on other volumes… Though in theory it should work just fine.

    Also (unrelated), sure you don’t need the E parameter? Read the first five comments, and if it’s not throwing errors at you maybe you should include it.

  26. 26. Comment by Mike
    on 7 Nov 2007 @ 10:00 pm

    Good catch on me missing the -E flag.

    I figured it out, tho: the script ran fine from the Terminal, but not from AppleScript. The reason was because the “with administrator privileges” I was adding in AppleScript was ditching the flags with “–” in front of them.

    I’d classify this as a bug in AppleScript.

    I added the script to the system crontab to run as root, and it’s working fine now.

  27. 27. Comment by Biogeek
    on 17 Nov 2007 @ 6:12 am

    I’m using 10.4.9, and when I try to compile or save rsync, it tells me that it expected the end of a line, but found an unknown token… I’m not familiar with any programming languages, so it’s probably something stupid, but… Any help?

  28. 28. Comment by Mark
    on 21 Nov 2007 @ 7:06 am

    Same here Biogeek. It is just the way the code has come up on this page.

    Wherever the script says “&” followed by “amp” and a semi colon (;) you have to replace that with just the “&” sign. I hope that makes sense. Just use ‘Find’ from the Edit menu in Script Editor.

  29. 29. Comment by Mark
    on 21 Nov 2007 @ 7:11 am

    I just tested it and that’s the problem. Just substitute the “& amp;” bit with the “&” symbol.

    Constantinos I think there is a problem with the way your blog displays code when it comes to the & symbol. Just a bit confusing for us Applescript n00bs. 🙂

    Anyway, love your site and your bits of code!

    Cheers,
    Mark

  30. 30. Comment by Mark
    on 21 Nov 2007 @ 9:09 am

    I have tried to do the script in reverse (Auto backup *to* a flash drive). I don’t get any errors but it doesn’t do the backup. Any ideas on what I’m doing wrong? I’m trying to backup the “Pending” folder that is on my Desktop.

    (I removed all the archive stuff because I don’t need it.)

    Thanks in advance,
    Mark

    property with_administrator_privileges : false
     
    property display_notification : true
     
    property rsync_params : "-aEz --delete-excluded"
    (* END OF PREFERENCES *)
     
    set WhereImRunningFrom to path to me
    tell application "Finder"
    	(* can't run from the script editor *)
    	set AppCreator to creator type of WhereImRunningFrom
    	if AppCreator is "ToyS" then
    		activate of me
    		beep
    		display alert "This script cannot run directly from ScriptEditor"
    		return
    	end if
     
    	(* NEVER run from the hard drive! *)
    	set bootVolume to name of disk of home (* safety feature! *)
    	set NameOfDisk to name of disk of WhereImRunningFrom
    	if NameOfDisk is bootVolume then
    		beep
    		display alert "Should not run this script from the boot volume!"
    		return
    	end if
     
    	(* find source and target *)
     
    	set targetDir to quoted form of ("/Volumes/" & NameOfDisk & "/")
    	set sourceDir to quoted form of ("/Volumes/Machintosh HD/Users/mark/Desktop/Pending/")
     
    end tell
     
    (* do the backup *)
    (* try *)
    if with_administrator_privileges then
    	set excluded to " "
    else
    	set excluded to " --exclude='.Trash*' --exclude='.Spotlight*'  "
    end if
     
    set theScript to "rsync " & rsync_params & excluded & sourceDir & " " & targetDir & "; touch " & targetDir
     
     
    if with_administrator_privileges then
    	do shell script theScript with administrator privileges
    else
    	do shell script theScript
    end if
     
    activate of me
    beep
    if display_notification then display alert NameOfDisk & " drive backed up"
    (*
    on error
        display alert "There was an error backing up " & NameOfDisk
    end try
    *)

  31. 31. Comment by Constantinos
    on 21 Nov 2007 @ 10:10 am

    [quote comment=”2105″]Same here Biogeek. It is just the way the code has come up on this page.

    Wherever the script says “&” followed by “amp” and a semi colon (;) you have to replace that with just the “&” sign. I hope that makes sense. Just use ‘Find’ from the Edit menu in Script Editor.[/quote]

    Thanks Mark, I recently upgraded my code highlighting plugin, and I didn’t notice this bug! Now fixed..

  32. 32. Comment by Constantinos
    on 21 Nov 2007 @ 10:23 am

    [quote comment=”2107″]Any ideas on what I’m doing wrong?[/quote]

    Not really. What I suggest you try is put a line like

    display alert theScript

    and then paste that line into the terminal and make sure it works there. If it does, then there’s definitely something wrong with the applescript logic itself and more investigating will be necessary. If it doesn’t, then try to find what the error is from the output in the terminal. The problem will most likely be in the way the command line is generated.

  33. 33. Comment by Mark
    on 21 Nov 2007 @ 11:10 am

    Thanks Constantinos for the quick reply!

    I pasted that that bit of code into rsyc.app and got the following alert:

    rsync -aEz –delete-excluded –exclude=’.Trash*’ –exclude=’.Spotlight*’ ‘/Volumes/Machintosh HD/Users/mark/Desktop/Pending/’ ‘/Volumes/BACKUP/’; touch ‘/Volumes/BACKUP/’

    [BACKUP is the name of my USB flash drive.]

    I ran the following command in the Terminal:

    /volumes/backup mark$ ./rsync.app display alert theScript

    and got the same alert.

    So that means there is something wrong with the applescript?

  34. 34. Comment by Constantinos
    on 21 Nov 2007 @ 11:50 am

    run this in the terminal:

    rsync -aEz –delete-excluded –exclude=’.Trash*’ –exclude=’.Spotlight*’ ‘/Volumes/Machintosh HD/Users/mark/Desktop/Pending/’ ‘/Volumes/BACKUP/’; touch ‘/Volumes/BACKUP/’

    If that gives you errors, then it’s the script.

    Be careful when copy/pasting code from the comment threads on my blog, as ‘special’ characters get ‘prettified’ in the comments…

  35. 35. Comment by Mark
    on 21 Nov 2007 @ 12:10 pm

    ok I got the following error:

    rsync: -delete-excluded: unknown option
    rsync error: syntax or usage error (code 1) at /SourceCache/rsync/rsync-24.1/rsync/main.c(1099)

    Any ideas?

  36. 36. Comment by Mark
    on 21 Nov 2007 @ 12:12 pm

    Sorry Correction:

    This is the error I got:

    rsync: link_stat "/Volumes/Machintosh HD/Users/mark/Desktop/Pending/." failed: No such file or directory (2)
    rsync error: some files could not be transferred (code 23) at /SourceCache/rsync/rsync-24.1/rsync/main.c(717)

  37. 37. Comment by Mark
    on 21 Nov 2007 @ 12:20 pm

    Sorry my bad. I’m an idiot. Thanks for your help though. Here is what it should be

    rsync -aEz --delete-excluded --exclude='.Trash*' --exclude='.Spotlight*' 'Desktop/Pending/' '/Volumes/BACKUP/'; touch '/Volumes/BACKUP/'

    i.e. no slash before Desktop

    Thanks again Constantinos (and for putting up with my stupid questions 🙂 )

  38. 38. Comment by Constantinos
    on 21 Nov 2007 @ 1:33 pm

    [quote comment=”2114″]Thanks again Constantinos (and for putting up with my stupid questions 🙂 )[/quote]

    No such thing as a stupid question, I once spent 15 hours debugging a piece of code where the only issue was something very similar to this, sometimes you just need someone else to point you in the right direction 🙂

    Both should work, assuming you didn’t misspell anything 🙂
    If you really want to make it ‘global’ per se, you could replace sourceDir with '~/Desktop/Pending/', or even '/Volumes/' & name of disk of home & '/Users/mark/Desktop/Pending/', and even better replace ‘mark’ by the current user’s short username (not sure how you’d retrieve that in applescript, thought it should be simple enough. The ~/Desktop/Pending/ version should work just as well though, if not better… Then you’re guaranteed that you’re syncing with the current user’s desktop, though that might get you into problems if you try to use the same script while logged in as someone else, or on a different computer… 🙂

  39. 39. Comment by Mark
    on 21 Nov 2007 @ 11:51 pm

    Thanks Constantinos!!!!

    Seems to be working now! I used '/Volumes/' & name of disk of home & '/Users/mark/Desktop/Pending/'

    A noticed a few things:
    1) I had to make sure there was a double dash (-) in the Applescript for the rsync parameters.
    2) When I mount my USB I get an Applescript alert from rsync.app saying “Press Run to run this script, or Quit to quit.” How do I stop this from coming up?
    3) Sometimes I get an error that the script can’t find the volume BACKUP (name of my USB drive). Is that because the script is running before the drive has properly mounted?

  40. 40. Comment by Constantinos
    on 22 Nov 2007 @ 12:00 am

    [quote comment=”2116″]A noticed a few things:
    1) I had to make sure there was a double dash (-) in the Applescript for the rsync parameters.
    2) When I mount my USB I get an Applescript alert from rsync.app saying “Press Run to run this script, or Quit to quit.” How do I stop this from coming up?
    3) Sometimes I get an error that the script can’t find the volume BACKUP (name of my USB drive). Is that because the script is running before the drive has properly mounted?[/quote]

    1) yup, that’s correct… the html in the comments converts two dashes to a single ‘double’ dash
    2) I think this has to do with the way you saved the script… I don’t remember exactly what options you have to use, I think it’s “Run only” or something like that.
    3) I think so. You can try adding a small delay at the beginning of the script.

  41. 41. Comment by Mark
    on 22 Nov 2007 @ 2:50 am

    Thanks again Constantinos!

    I added a delay to the folder action script which has fixed the mounting issue.

    Re the alert: I unclicked the “Start up screen” option in the save dialog.

    Working great! Thanks

  42. 42. Comment by The Doctor What
    on 11 Jan 2008 @ 3:23 am

    I like the idea. I’m trying to get it to run a shell script (‘backup.sh’) instead.

    However, it doesn’t seem to be working. I don’t know enough about apple script to really trouble shoot it.

    Hints? A tutorial on writing Apple Script for people that can write many other languages?

    An already written script? ^_^

    Ciao!

  43. 43. Comment by Constantinos
    on 11 Jan 2008 @ 8:48 am

    Well, this wouldn’t involve much apple scripting, would it? The on mount stuff would work in exactly the same way. If you write your ‘backup.sh’ script and debug it while the device is plugged in, all you really need is a minor change in the folder action. Simply replace the line that says

    		open item j of file_list

    with a line that says

    		set script_path to quoted form of POSIX path of item j of file_list
    		do shell script script_path

    All this is provided you changed the name of the “rsync.app” at the top to “backup.sh”.

  44. 44. Comment by Greenleaf
    on 14 Jan 2008 @ 3:51 pm

    I’m having a small problem with this script on my wife’s iMac. I set everything up and initially tested it from the admin account, but I cannot get it to automatically back up any flash drives from any other account. I added the folder action from mine and my wife’s accounts (regular accounts, not admins) and have made sure the script can be read by those accounts, but it just doesn’t seem to work. I can manually back up the flash drives by double-clicking the rsync script, but I really want to make it work automatically, otherwise it won’t really do any good, because it won’t get used.

  45. 45. Comment by The Doctor What
    on 14 Jan 2008 @ 6:22 pm

    [quote comment=”2163″]Well, this wouldn’t involve much apple scripting, would it? [/quote]

    Thanks! That’s the part I didn’t know. My shell scripting is excellent. AppleScript is something I played with once when Mac OS was version 4 or 5 on a Hypercard stack.

    Ciao!

  46. 46. Comment by Michael
    on 29 Jan 2008 @ 3:08 am

    I had this script “installed” as suggested on my thumb drive, and under Tiger, it worked perfectly. Automatic backups! However, upon upgrading my computer to Leopard, it stopped backing up automatically. Like Greenleaf (Comment #45) mentioned, it still works perfectly when I double-click the rsync app, but only then.

    Does anyone have any suggestions?

    This script is *magnificent* and I was bummed when I discovered that it wasn’t working as it had used to.

  47. 47. Comment by Greenleaf
    on 30 Jan 2008 @ 5:27 pm

    [quote comment=”2164″]I’m having a small problem with this script on my wife’s iMac. I set everything up and initially tested it from the admin account, but I cannot get it to automatically back up any flash drives from any other account. I added the folder action from mine and my wife’s accounts (regular accounts, not admins) and have made sure the script can be read by those accounts, but it just doesn’t seem to work. I can manually back up the flash drives by double-clicking the rsync script, but I really want to make it work automatically, otherwise it won’t really do any good, because it won’t get used.[/quote]
    Perhaps I should clarify what version of OS-X I’m using this on. The iMac is running Tiger, and is kept up to date on downloading updates. The script worked perfectly when I used it from the admin account, but not from any other accounts unless I manually run the script from the flash drive. All the flash drives are formatted FAT32 so they can be used with any computer, though I doubt that’s the issue, since manual backup still works.

    Help please!

  48. 48. Comment by Matt
    on 8 Feb 2008 @ 1:15 pm

    Hi, I’ve never used applescript before, but by following your instructions I easily got my usb flash drive to auto backup when inserted. You mentioned in your instructions that an optional tar-gzipped archive can also be created. Can you point me in the right direction as to how I might implement this as I can’t see any references to it in the applescript code itself? Thanks.

  49. 49. Comment by Constantinos
    on 8 Feb 2008 @ 5:46 pm

    [quote comment=”2210″]Hi, I’ve never used applescript before, but by following your instructions I easily got my usb flash drive to auto backup when inserted. You mentioned in your instructions that an optional tar-gzipped archive can also be created. Can you point me in the right direction as to how I might implement this as I can’t see any references to it in the applescript code itself? Thanks.[/quote]

    Well, the way to do that is to add another shell command after the first one, which will tar-gzip the newly-created backup folder. After the if block near the end which starts with if with_administrator_privileges then do shell script ..., add another if block like this:

    if archive_backup then
    	do shell script "tar -czf " & backup_folder & backupBase & thedate & ".tgz " & backupFolder
    else
    	do shell script "tar -czf " & targetDir & ".tgz " & targetDir
    end if

    This *should* tar-gzip the folder that was just created. If you’re using archive backups, it will create a .tgz file for each dated backup, and you’ll need more code in the applescript itself to clean those out. If you’re not using archive backups, this command will overwrite the .tgz file every time…

    I have NOT tested this, and I just hard coded it here – proceed with caution. You’d need more extensive applescripting to get everything to work properly – i.e. delete old tarballs, or maintain only one full backup but have multiple tarred backups, etc. Hope this helps.

  50. 50. Comment by Matt
    on 11 Feb 2008 @ 10:11 am

    Thanks Constantinos. I think it’s probably best that for now I leave the script ‘as is’. At the moment I don’t know anything about applescripting – all I can do is cut and paste. Thanks for sharing your solution with us though, it’s really helpful!