I have an applescript that is used to copy a file (using rsync) from a source to a multitude of locations:
set Servers to {"afp://service.username:password#MACSERVER1.domain.com/Public/", "afp://service.username:password#MACSERVER2.domain.com/Public/", "afp://service.username:password#MACSERVER3.domain.com/Public/", "afp://service.username:password#MACSERVER4.domain.com/Public/", "afp://service.username:password#MACSERVER5.domain.com/Public/"}
--these are constant so no need to change
set Source to "/Shared Items/Public/DeployStudio/Masters/HFS/Sierra.hfs.dmg"
set Destination to "/Volumes/Public/DeployStudio/Masters/HFS"
--the scripts that goes recursively through the list of servers
repeat with i from 1 to count of Servers
set thisServer to item i of Servers
--this will mount each server destination in turn creating a /Volumes/Public folder
mount volume thisServer
--these are two rsync scripts which creates logfiles
do shell script "/usr/bin/rsync -rlptD --log- file=/Users/username/Documents/logs/Sierra-rsync.log " & (quoted form of Source) & " " & (quoted form of Destination)
--not sure this is needed but added this 5 sec delay to stop ejecting disk errors
delay 5
--eject the mounted volume so we don't have multiple Public folders
tell application "Finder"
eject disk "Public"
end tell
end repeat
This works great and produces a log of what it does. Unless there is a problem. Then it will just quit. I would like to change it so it ignores errors and keeps going. Any ideas? Thanks
To ignore errors in the repeat loop wrap the affected code in a try block
repeat with i from 1 to count of Servers
set thisServer to item i of Servers
try
...
end try
end repeat
Related
Please help, I can't think of a fix for this.
A folder action is meant to do this for each file copied into a folder:
Derive a subfolder name, and a new filename.
Create subfolder.
Move file into it.
Rename subfolder and file.
Files are copied from a different volume and are usually 500…1500 MB.
Problem: The moving step (step 3) in the folder action script fails if the files are that large and their number is >1
and they are copied from a different volume.
The script works fine when copying: small files, or from the same volume, or only one file.
In a test, all of 200 Alias' were correctly processed, but only 23 of 512. This is not a problem, the number of added_items is usually <10 and unlikely to ever be >50. But it may help targeting the issue.
I suspected a timing issue, but all attempts to fix it using generous timeout's didn't work.
The script (note - before trying, set the regex in the do shell script lines to something workable):
on adding folder items to this_folder after receiving added_items
repeat with the_item in added_items
with timeout of 3600 seconds
tell application "Finder"
if kind of the_item is not "Folder" then
repeat -- wait until item is copied. Thanks to original coder on the WWW.
set {size:fileSize, busy status:Busy} to (info for (the_item))
if not Busy and (fileSize is greater than 0) then exit repeat
delay 1
end repeat
with timeout of 600 seconds
set new_folder_name to do shell script "echo '" & (name of the_item) ¬
& "' | sed -E 's/llooongRegex/replace/g'"
set new_item_name to do shell script "echo '" & (name of the_item) ¬
& "' | sed -E 's/otherRegex/replace/g'"
set new_folder to (make new folder at this_folder with properties {name:(new_folder_name & "-temp")}) as alias -- "-temp" in case new folder and file will have the same name
move file the_item to folder new_folder -- <== fails if ((added_items >1) AND (files big, tested with 0.5…1.5GB) AND (copied from different volume)) ==> Timing issue?
set name of (first item of (get contents of new_folder)) to new_item_name
set name of new_folder to new_folder_name
end timeout
end if
end tell
end timeout
end repeat
end adding folder items to
P.S.: is folder-action frequent enough for a tag?
After replacing the repeat -- wait until item is copied.... clause with a simple delay 60, the script works. So it is a timing problem.
Waiting for the target folder to stop changing size as describe here works as long as only 1 file copying (bunch of files dropped) is running. Two or more drag'n drops, and it hiccups again (nice word, #vadian!).
Ditto when checking for the size of individual added items to remain constant.
I have all these movies in .dvdmedia format and I want to covert them all to a smaller file size such as .mp4.
But what I need to do is create an applescript that will copy the individual file to a folder 'Conversion'. Once the file in the folder is deleted it copies the next item and deletes the previous.
I've completed an Automation script that once the item is added to the folder is starts formatting the file through TurboHD then deletes the file and moves the converted item to another folder 'Completed'
Does anyone able to help me with this?
Please note that the location of the movies are on a NAS drive
there :) I coded the following. Please note to save it as an Application with Stay open after run handler checked.
You have to set the source and the target path to the paths in your environment.
Finally you have to set the return value. The value sets the interval in seconds to wait until next execution. If each of your conversions takes about an hour, I think I would check every 5 minutes meaning the handler has to return 300.
-- The idle-Handler defines a repetitive task
-- Note: Save as Application with option "Stay open after run handler"
on idle
-- define the folders to watch
set theSourceFolder to (POSIX file "/Users/myHomeFolder/Desktop/Conversion_Source") as alias
set theTargetFolder to (POSIX file "/Volumes/myMountedVolume/Conversion") as alias
-- check the contained files (get visible files only because of .DS_Store etc.)
tell application "System Events"
set availableSourceFiles to every file of theSourceFolder whose visible is true
set filesOfTargetFolder to files of theTargetFolder whose visible is true
end tell
-- if no more source file is available, quit this script
if (count of availableSourceFiles) = 0 then
quit
end if
-- if the target folder is empty start move
if (count of filesOfTargetFolder) = 0 then
-- get the first item from source folder
set sourceFile to (first item of availableSourceFiles) as alias
-- use the Finder to copy the file
tell application "Finder"
-- duplicate the file to the target folder
duplicate sourceFile to theTargetFolder
-- move the source file to trash after copy
move sourceFile to trash
end tell
end if
-- the integer returned is the time to wait (in seconds)
-- here: two minutes
return 120
end idle
Enjoy, Michael / Hamburg
I'm trying to get duplicate home folders (desktop, movies, music, home, etc..) to a shared server. I was finally able to get the drive mounted using a concatenation of string and variables. But now i'm getting an error on the duplication line. If I mount the drive manually, this code works, but doesn't seem to work when mounting the drive through applescript
--Assigns variable to username
tell application "System Events"
set user_name to name of current user
end tell
--Prompts for eraider as string
set returnedName to (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets string as variable
set work_name to text returned of returnedName
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to {choose from list deptList} as string
--Tells Finder to mount shared drive
tell application "Finder"
mount volume ("smb://vserver/athletics/"&dept_name&"/"&work_name)
end tell
--Sets sever as variable
set vserver to POSIX file ("/Volumes/" & work_name)
--Copies Documents to Server
set source to POSIX file ("/Users/" & user_name & "/Documents")
tell application "Finder"
duplicate source to vserver with replacing
end tell
I get this error
error "Finder got an error: AppleEvent handler failed." number -10000
On this line: duplicate source to vserver with replacing
You have a few strange things in your code. Most of them do not affect your error however they should be corrected. For example the "mount volume" command is not a Finder command, it's an applescript command and thus you should not tell the Finder to perform that command. Next, the "choose file" line... why do you have brackets around it? Plus other small things. So I cleaned up the code.
To get to your specific problem it could be 2 things. First, I use an if statement to ensure the disk is mounted before trying to duplicate the files. Second, the "POSIX File" command could also cause problems. It's an unusual command in that it doesn't always work the way you expect. Therefore in this code, to ensure we avoid any issues with that command, I coerce it to text and then in the duplicate command I put it in the proper format by using the word "folder" in front of it.
So I did not test this code but it should work. I hope it helps.
--Assigns variable to username
tell application "System Events" to set user_name to name of current user
--Prompts for eraider as string
set work_name to text returned of (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to item 1 of (choose from list deptList)
--mount shared drive
mount volume ("smb://vserver/athletics/" & dept_name & "/" & work_name)
if work_name is in (list disks) then
--Copies Documents to Server
set source to (POSIX file ("/Users/" & user_name & "/Documents")) as text
tell application "Finder" to duplicate folder source to disk work_name with replacing
else
display dialog "Disk " & work_name & " is not mounted"
end if
An even better way would be to use the "path to" command to establish the path to your documents folder. This way you don't need to use "POSIX File" or even know the user name because the "path to" command automatically works for the current user. Plus I would do a little more error checking on the mount volume stuff. So really this is how I would write your code... I didn't test this either!
--Prompts for eraider as string
set work_name to text returned of (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to item 1 of (choose from list deptList)
--mount shared drive
set isMounted to false
if work_name is not in (list disks) then
mount volume ("smb://vserver/athletics/" & dept_name & "/" & work_name)
-- wait for the volume to be mounted but only wait for a limited time before failing (10 seconds in this case)
set inTime to current date
repeat
delay 0.2
if work_name is in (list disks) then
set isMounted to true
exit repeat
end if
if (current date) - inTime is greater than 10 then exit repeat
end repeat
else
set isMounted to true
end if
--Copies Documents to Server
if isMounted then
set source to path to documents folder
tell application "Finder" to duplicate source to disk work_name with replacing
else
display dialog "There was an error mounting disk " & work_name buttons {"OK"} default button 1
end if
I'm fairly new at this and while having managed to created several basic scripts over the last few weeks I cannot seem to wrap my head around this one:
Choose Folder (with say 1000 Files)
Enter the number of Files per Folder (say 100)
The script then creates 10 Folders (1000 Files / 100 in each folder)
The script then moves the first 100 files sequentially into the the first folder - repeats till done.
The scripts I've put together for this process to this point are dismal, sloppy and outright pathetic so I dare not share them here.
My experiments have also resulted in the item listing causing issues with moving the files sequentially.
instead of:
ValOne_1.wav
ValOne_2.wav
ValOne_3.wav
ValOne_4.wav
ValOne_5.wav
I get:
ValOne_1.wav
ValOne_10.wav
ValOne_100.wav
ValOne_101.wav
ValOne_102.wav
Thanks
The Finder has a "sort" command so you can use that to avoid the numbering problem you mention. It seems to sort them the way you expect. So using that your workflow becomes easy with a little clever coding. Try the following. You only need to adjust the first 2 variables in the script to suit your needs and the rest of the script should just work.
set filesPerFolder to 3
set newFolderBaseName to "StorageFolder_"
set chosenFolder to (choose folder) as text
tell application "Finder"
-- get the files from the chosen folder and sort them properly
set theFiles to files of folder chosenFolder
set sortedFilesList to sort theFiles by name
set theCounter to 1
repeat
-- calculate the list of files to move
-- also remove those files from the sortedFilesList
if (count of sortedFilesList) is greater than filesPerFolder then
set moveList to items 1 thru filesPerFolder of sortedFilesList
set sortedFilesList to items (filesPerFolder + 1) thru end of sortedFilesList
else
set moveList to sortedFilesList
set sortedFilesList to {}
end if
-- calculate the new folder information and make it
set newFolderName to newFolderBaseName & theCounter as text
set newFolderPath to chosenFolder & newFolderName
if not (exists folder newFolderPath) then
make new folder at folder chosenFolder with properties {name:newFolderName}
end if
-- move the moveList files
move moveList to folder newFolderPath
if sortedFilesList is {} then exit repeat
set theCounter to theCounter + 1
end repeat
end tell
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
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
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.
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.
I changed the wording of the duplicate statement from duplicating every "file" to duplicating every "item" so that folders are duplicated too.
I put in an on-error block in the try-statement to display any errors.
I activate Finder so that you can see the progress window.
I pop up a dialog at the end if there were no errors.
I had a problem that I had to fix:
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
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.
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