AppleScript Folder Actions: Add action to subfolders, rsync on add/remove

Discussion in 'Mac Programming' started by maztec, Apr 12, 2011.

  1. maztec, Apr 12, 2011
    Last edited by a moderator: Apr 13, 2011

    macrumors newbie

    Joined:
    Jan 18, 2011
    #1
    Greetings.

    This is my first real attempt at doing something with AppleScript, which may explain why I am having trouble with it. I searched for similar topics but did not find anything that revealed to me what I was doing wrong or another way of doing this, but did find a few topics that gave me hints that got me this far. If those exist, my apologies and please accept my humble request for a link to the appropriate location.

    I have been playing around with this script for a few weeks. What I am wanting to do is set up a script so that anytime I add a new file or remove a file from my Documents directory, the directory is automatically rsync'd to my remote server. For reasons that I do not feel like going into, I cannot use Dropbox or some other product for this and really would rather do it myself.

    Necessary Features:
    *) Rsync to remote server when file added to or removed from Documents directory [working]
    *) Rsync to remote server when documents added to subdirectory [not working]
    *) Folder action added to subfolders automatically, when a subfolder is added - so that when new documents are added to those folders rsync to remote server is triggered [broken]

    Wanted Future Features, after I fix what is already broken:
    *) When folder removed from Documents the folder action should automatically be removed.
    *) Stop folder actions from making the Documents folder "blink" when activated.
    *) Rsync when files are modified - not just added or deleted.

    Here is the code snippet that is generating an error. The error is "Can't get folder of alias:".

    Open this Scriplet in your Editor:

    Code:
        on updateFolders(each_item)
           notify("1")
    
        -- This is where I am getting an error. The "if class of each_item is folder" never seems to work. I have wrapped this a dozen different ways and just do not seem to be getting anywhere with it. I think it has something to do with the type that each_item is, but even adjusting that and trying to munge it about doesn't seem to be doing anything.
           if class of each_item is folder then
               notify("2")
               tell application "Finder" to set theSubItems to (every item of each_item as alias list)
               repeat with thisItem in theSubItems
                   notify("3")
                   tell application "System Events" to attach action to thisItem using SCRIPTPATH
                   notify("4")
                   updateFolders(thisItem)
               end repeat
           end if
           return
        end updateFolders
    Note, I admit that I used someone else's code for some of this. I cannot remember who offhand, but if I do I will be sure to annotate it with that information.

    Here is the entire script, with remote server information removed:

    Open this Scriplet in your Editor:


    Code:
        -- Variables used by RSYNC
        global SOURCE
        global TARGET
        global PARAMETERS
        global MODE
        global SCRIPTPATH
        global SCRIPTNAME
    
        -- Initializes the RSYNC parameters and registers the script with GROWL
        on init()
           set TARGET to "me@myserver.com:directory/"
           set SOURCE to "/Users/MyUser/Documents"
           set PARAMETERS to "-ra --delete-after -e ssh --out-format \"" & (ASCII character (37)) & "o " & (ASCII character (37)) & "n\" --exclude=\".DS_STORE\" "
           set MODE to "growl"
           -- set MODE to "dialog" -- use dialogs instead of growl if not installed.. snipped this code from someone, embarrassingly enough I cannot remember who or where, sorry :(.
           set SCRIPTNAME to "sync JDocuments folder.scpt"
           set SCRIPTPATH to ((path to Folder Action scripts) as text) & SCRIPTNAME
           
           -- If we are using growl we need to register this script with growl    
           if MODE is "growl" then
               tell application "GrowlHelperApp"
                   set the allNotificationsList to {"sync"}
                   set the enabledNotificationsList to allNotificationsList
                   register as application ¬
                       "SHARED folder actions" all notifications allNotificationsList ¬
                       default notifications enabledNotificationsList ¬
                       icon of application "Script Editor"
               end tell
           end if
        end init
    
        -- Synchronize the folders specified in SOURCE and TARGET using rsync
        on synchronize(local_folder)
        -- gratuitous sync messages used while debugging.
           notify("Synchronizing")
    
           set message to do shell script "rsync" & " " & PARAMETERS & " " & SOURCE & " " & TARGET
    
           notify("Synchronized")
           return message
        end synchronize
    
        on updateFolders(each_item)
           notify("1")
    
        -- This is where I am losing it. the "if class of each_item is folder" never seems to work. I have wrapped this a dozen different ways and just do not seem to be getting anywhere with it. I think it has something to do with the type that each_item is, but even adjusting that and trying to munge it about doesn't seem to be doing anything.
           if class of each_item is folder then
               notify("2")
               tell application "Finder" to set theSubItems to (every item of each_item as alias list)
               repeat with thisItem in theSubItems
                   notify("3")
                   tell application "System Events" to attach action to thisItem using SCRIPTPATH
                   notify("4")
                   updateFolders(thisItem)
               end repeat
           end if
           return
        end updateFolders
    
        -- These two functions are called by the folder actions. they initialize the system according to preferences and then call the chosen notification system
        on adding folder items to this_folder after receiving added_items
           init()
           notify(POSIX path of this_folder)
           repeat with each_item in added_items
               notify("repeat for each item")
               set message to updateFolders(each_item)
           end repeat
           set message to synchronize(POSIX path of this_folder)
           notify(message)
        end adding folder items to
    
        on removing folder items from this_folder after losing removed_items
           init()
           notify("removed")
        -- this is where I need to add the remove action script from subfolders if removed from the directory.
           set message to synchronize(POSIX path of this_folder)
           --notify(message)
        end removing folder items from
    
        -- Sends an even to growl about modified files or open a dialog with the same information
        on notify(message)
           -- let's avoid empty notifications (silly)
           if message is not "" then
               if MODE is "growl" then
                   tell application "GrowlHelperApp"
                       notify with name ¬
                           "sync" title ¬
                           "Folder updated" description ¬
                           message application name "SHARED folder actions"
                   end tell
               else if MODE is "dialog" then
                   display dialog the ("folder update complete") giving up after 5
               end if
           end if
        end notify
    
    
        -- This function is just for testing, anything in here is executed by pressing "RUN" in the Applescript editor
        on run
           -- Initialize
        -- various silly things I have done to test it at different times.
           init()
    
        -- not doing anything at the moment.
        end run
    Any help, especially with the error I am getting now would be appreciated. Suggestions for the other features I want to add would also be great, but my first focus is to debug what exists. If there is a better way to do all of this, I am all ears.

    Thanks!
     

Share This Page