0

I am writing a script to allow students to upload their files to a shared folder on teacher's computer in a computer lab (same network). I have a working script that, when executed, will duplicate all files in the folder UPLOAD on the student machine to the folder SUBMISSIONS on the teacher's machine. However, if a file already exists on the teacher machine, the script hangs.

I need to be able to test for the presence of individual files on the teacher machine and either (a) pop a message that says "this file already exists, rename it and upload again" or (b) append something to the file name to differentiate it...a random number or "copy 1" etc.

Ideally I want it to run as a folder action. When a file is added to the "UPLOAD" folder it will automatically be sent to the teacher. But I don't want files to copy over files of the same name...or for the script to hang.

Any thoughts or alterative approaches would be welcome.

Here's my code:

set home_path to path to home folder as string
set work_folder to alias (home_path & "Desktop:" & "Upload")

try
    mount volume "afp://[LOGIN INFO].local/Submissions"
    set this_folder to result as alias
    tell application "Finder"
        tell application "Finder"
            duplicate every file of work_folder to this_folder
        end tell
        eject this_folder
    end tell
end try

4 Answers4

0

I think that it would help if your try-block had an on-error block to inform you about any errors.

try
    # try stuff here
    j # this will compile but will throw a runtime error and you can see the error
on error error_message number error_number
    display alert "Error: " & error_message & return & return & (error_number as text)
end try
Kaydell
  • 484
  • 1
  • 4
  • 14
0

This script will copy each file over to the mounted volume. If a file exists with the same name at the destination it will add a number to the end of the copy file name and try that.

Example:if test.doc exists in the folder already then the script will try and copy it with the name test_1.doc and so on..

The original file is never renamed and the older files are never overwritten. The script is fully commented to explain what it is doing.

** Update2 **

The copy to destination code is now in it's own handler. The original files are labeled by the finder label index 6 (green) to indicate successful copied.

This will also stop the same original file from being copied twice by using the index colour as a check. If it is labeled index label 7 it will be ignored.

You could if you want move the successful copied files to another folder out of the way using the script. But I have not done this in this script.

            set home_path to path to home folder as string
        set work_folder to alias (home_path & "Desktop:" & "Upload")
        set counter to ""
        global counter
        --try

        set this_folder to mount volume "afp://myMac/UserName/"
        this_folder as text


tell application "Finder" to set theFiles to every file of work_folder as alias list #GET ALL FILES OF LOCAL FOLDER AS ALIASES
tell application "Finder" to set theRemoteFiles to (every file of ((this_folder & "Submissions:" as string) as alias)) #GET ALL FILES OF REMOTE FOLDER -- ONLY NEEDED FOR COUNT CHECK LATER

repeat with i from 1 to number of items in theFiles #PROCESS EACH LOCAL FILE 

    set this_item to item i of theFiles #GET A LOCAL FILE
    tell application "Finder" to set LabelIndex to label index of this_item
    if LabelIndex is not 6 then
        tell application "Finder" to set this_name to displayed name of this_item #GET ITS DISPLAYED NAME
        tell application "Finder" to set this_extension to name extension of this_item #GET ITS EXTENSION NAME i.E "txt"
        set realName to (do shell script "echo " & quoted form of this_name & "| awk -F '" & quoted form of this_extension & "' '{print $1}'") #GET ITS NAME WITHOUT EXTENSION NAME

        set counter to 1 # SET A NUMBER TO ADD TO THE FILE NAME IF THE FILE NAME EXIST ALREADY IN THE REMOTE FOLDER
        my checkName(this_name, realName, this_item, this_extension, theRemoteFiles, this_folder) # CALL TO HANDLER THAT WILL DO THE CHECKING AND COPYING
    end if

end repeat
tell application "Finder" to eject this_folder

# THE  CALL TO THE HANDLER INCLUDES VARIABLES THAT ARE NOT GLOBAL OR PROPERTIES BUT NEED TO BE PASSED ON TO IT  I.E(this_name, realName, this_item, this_extension, theRemoteFiles, this_folder)
on checkName(this_name, realName, this_item, this_extension, theRemoteFiles, this_folder)


    # (1) IF THE NUMBER OF theRemoteFiles IS GREATER THAN 0 THEN FILES EXIST IN THE REMOTE FOLDER AND MAY CONTAIN FILES WITH THE SAME NAMES AS THE LOCAL ONES. PROCESS..
    # (2) IF THE NUMBER OF theRemoteFiles IS NOT GREATER THAN 0.THEN FILES DO NOT EXIST IN THE REMOTE FOLDER AND THE LOCAL ONES CAN JUST BE COPIED OVER.
    if (count of theRemoteFiles) is greater than 0 then # (1)

        try
            my copyOver(this_item, this_folder, this_name)

        on error errMssg #WE USE not overwritten ERROR TO TRIGGER THE RENAME THE DESTINATION  FILE NAME TO INCLUDE A NEW NUMBER.
            --tell application "Finder" to set label index of this_item to 6
            if errMssg contains "not overwritten" then

                set this_name to (realName & counter & "." & this_extension)
                set counter to counter + 1 #WE SETUP THE FILE NAME NUMBER FOR THE POSSIBLE NEXT RUN

                # RUN THE HANDLER AGAIN WITH THE CHANED DETAILS
                my checkName(this_name, realName, this_item, this_extension, theRemoteFiles, this_folder)
            end if

        end try

    else # (2)
        my copyOver(this_item, this_folder, this_name)
    end if
end checkName

on copyOver(this_item, this_folder, this_name)
    # THE -n  OPTION IN THE SHELL COMMAND TELLS CP NOT TO OVERWRITE EXISTING FILES. AN ERROR OCCURE IF THE FILE EXISTS.
    # THE -p  OPTION IN THE SHELL COMMAND TELLS CP   TO PRESERVE THE FOLLOWING ATTRIBUTES OF EACH SOURCE FILE  IN THE COPY:
    # modification time, access time, file flags, file mode,
    #user ID, and group ID, as allowed by permissions.  Access Control
    #Lists (ACLs) and Extended Attributes (EAs), including resource
    #forks, will also be preserved.
    # THE -v  OPTION IN THE SHELL COMMAND TELLS CP TO USE VERBOS MODE. WHICH GIVES US A BETTER CLUE OF THE ERROR

    set theResult to (do shell script "cp -npv " & quoted form of (POSIX path of this_item) & space & quoted form of (POSIX path of (this_folder & "Submissions:" as string) & this_name))
    if theResult contains "->" then
        tell application "Finder" to set label index of this_item to 6
    else
        tell application "Finder" to set label index of this_item to 7
    end if

end copyOver
markhunte
  • 6,805
  • 2
  • 25
  • 44
  • Slight update to the handler to use the error message for a trigger rather than just any error from the cp shell command – markhunte Jun 29 '13 at 13:26
  • There is a new update ** Update2 ** which stops already copied files from being copied again. – markhunte Jun 30 '13 at 16:59
  • I think that posted fully working, coded examples can be good, but I think that it's good too to explain how you got the solution. – Kaydell Jul 02 '13 at 11:31
  • @Kaydell Sorry, what do you mean? – markhunte Jul 02 '13 at 17:20
  • Sorry, what I meant is that over at [javaprogrammingforums.com](http://www.javaprogrammingforums.com/content/45-problem-spoon-feeding.html), when I provided a good, complete, solution, a moderator there deleted my post and told me that I was "spoon-feeding" the original-poster (OP). This moderator threatened to suspend my account if I continued to "spoon-feed". You and I have both supplied complete code, but I don't feel like I'm through with this question yet. I'd like to explain to the OP how to tweak his code and make it work, or explain how my code works. That's what I mean. – Kaydell Jul 03 '13 at 00:06
0

OK. I tried again to write some code. Here is my version.

It does a couple of things differently than the code posted by the original poster.

  1. It copies the files and folders into a new folder on the server with a time-stamp to cope with the problems of whether some of the files already exist on the server.

  2. I changed the wording of the duplicate statement from duplicating every "file" to duplicating every "item" so that folders are duplicated too.

  3. I put in an on-error block in the try-statement to display any errors.

  4. I activate Finder so that you can see the progress window.

  5. I pop up a dialog at the end if there were no errors.

I had a problem that I had to fix:

  1. On the server, I had to enable write permissions for the client or I got a -5000 error.

I think that the following code should work pretty well. It's almost 100% AppleScript. It only uses one call to the shell and that is to get the current date and format it for the time-stamp for new folders created on the server.

# set the path to the "work_folder" where the files are to be uploaded
set home_path to path to home folder as string
set work_folder to alias (home_path & "Desktop:" & "Upload")

# duplicate the files and folders in work_folder to the server
try
    # TODO set the name of your server here
    set the_volume to mount volume "afp://32-bit.local/Submissions"
    set destination_path to the_volume as text
    set folder_name to getTimeStamp()
    tell application "Finder"
        activate
        set new_folder to make new folder at alias destination_path with properties {name:folder_name}
        duplicate every item of work_folder to new_folder
        eject the_volume
        display alert "Successfully uploaded the files and folders"
    end tell
on error error_message number error_number
    if error_number is not equal to -128 then
        display alert "Error: " & error_message & return & return & (error_number as text)
    end if
end try

# This function returns the current date and time as a time-stamp of the form yyyy-mm-dd-hh-ss
# This function uses a shell script because it's just a lot easier to do than in AppleScript
on getTimeStamp()
    set time_stamp to do shell script "date '+%Y-%m-%d-%H-%M-%S'"
    return time_stamp
end getTimeStamp
Kaydell
  • 484
  • 1
  • 4
  • 14
0

Here's another idea for debugging. You can put in calls to "display dialog" to be able to know where your script is failing:

display dialog "Entering script"
set home_path to path to home folder as string
display dialog "home_path: " & home_path
set work_folder to alias (home_path & "Desktop:" & "Upload")
display dialog "work_folder: " & work_folder as string

try
    mount volume "afp://32-bit.local/Submissions"
    set this_folder to result as alias
    display dialog "this_folder: " & this_folder as string
    tell application "Finder"
        display dialog "Inside of the first tell application Finder"
        tell application "Finder"
            display dialog "About to call duplicate"
            duplicate every file of work_folder to this_folder
            display dialog "Just returned from calling duplicate"
        end tell
        display dialog "About to call eject"
        eject this_folder
        display dialog "Just returned from call to eject"
    end tell
on error error_message number error_number
    display alert "Error:" & error_message & return & return & (error_number as text)
end try
display dialog "Exiting script"

Another debugging technique is to log output to a text file.

Another debugging technique is to purchase the AppleScript debugger:

http://www.latenightsw.com/sd4/index.html

I believe that this debugger costs $200.00 that's too pricey for me, but I've used other debuggers and debuggers are wonderful tools that let you "peek inside" of your script while it's running to see the value of variables and to trace which lines of code are being executed.

Kaydell
  • 484
  • 1
  • 4
  • 14