Hello - I would like some advice on improving my script. What it does is read the set of backup settings (each previously set up in SuperDuper!), and runs those jobs sequentially. It is rather inelegant as is, although basically functional. I would like better feedback from the script as to which copies have succeeded or failed; but the approaches that I have tried give me errors. I’ll start by listing the existing script and see if anyone is interested in helping.
-- Script by Al Cellier 2010-06-03
-- This Applescript needs YOUR folder name and needs YOUR settings files previously saved. No warranties, use at your own risk. Works for me.
-- Script will step through all files in folder "A>B" within the "Saved Settings" folder - Replace "A>B" in both places with "YOUR FOLDER"!
-- Pre-save YOUR settings files! The sequence is set by prefixing the settings filenames with 01, 02, 03 ...
-- For initial verification, the script displays a dialog showing the location, number of files, and filenames. If you click "OK" then it runs unattended.
-- At each file it calls on SuperDuper! to perform the backup, per the settings file. If you want to skip some, move them to a different folder temporarily.
tell application "Finder"
set Settingsfolder to POSIX file "/Users/acellier/Library/Application Support/SuperDuper!/Saved Settings/A>B/" as alias
set FileList to every file in Settingsfolder
display dialog (Settingsfolder & "
" & (number of items in FileList & " items in list
") & name of items of Settingsfolder & "
Power Up the Backup Drive 'B' before running!") as text
if (not (exists disk "DataB")) then
display dialog "PLEASE mount the backup drive!"
quit
end if
repeat with i from 1 to number of items in FileList
set NamedFile to (name of item i of FileList)
tell application "SuperDuper!"
try
delay 1
run using settings ("A>B/" & NamedFile) without user interaction
repeat while status is running
delay 12
end repeat
if status is done then
tell application "SuperDuper!" to quit
delay 2
--display dialog NamedFile & " copied ..." giving up after 2
end if
on error errMsg
display dialog "Oops! ... " & errMsg
end try
end tell
end repeat
end tell
with timeout of 43200 seconds -- 12 hours
display dialog ("Back ups All Complete !!
Dismount & Power down the backup drive 'X'")
end timeout
end
Model: iMac (early 2008)
AppleScript: 2.1.2
Browser: Firefox 3.6.24
Operating System: Mac OS X (10.6)
SuperDuper’s Scheduled copies is somewhat inflexible. In my case, I have several pairs of external hard drives, each with multiple partitions. For a given project I may need to backup several partitions, but not the entire set, for one or more pairs. With this script, it is easy to simply drag the settings files that I don’t want backed up to a “not now” folder, then run the script to back up exactly those still in the settings folder.
My script works OK as shown, but I am having problems with getting concise feedback. For example, when it runs, the script window’s Event Log / Events pane (for a single partition pair, of several) shows this :
tell application “Finder”
get name of document file “04 PhotA>B.sdsp” of folder “A>B” of folder “Saved Settings” of folder “SuperDuper!” of folder “Application Support” of folder “Library” of folder “user01” of folder “Users” of startup disk
→ “04 PhotA>B.sdsp”
end tell
tell application “SuperDuper!”
run using settings “A>B/04 PhotA>B.sdsp” without user interaction
get status
→ running
get status
→ running
get status
→ running
get status
→ running
get status
→ done
get status
→ done
quit
end tell
The number of times that the “running” status is displayed varies with the size of the partition, and makes it tedious to scroll through the result. I would like to have only a single flag of “running”. Thus, I need a suggestion for a better “repeat while” function.
I would like to have a display dialog show (individually, or cumulatively) the completion of that copy. But the display dialog that I have commented out, when enabled, results in a wordy error -1708 that I can not seem to defeat.
Also, I would like to have the script examine the SuperDuper log file at the end of each copy, and check the final line that the copy was completed OK. As it is, I have sometimes experienced bad copies due to lack of space on the target, and not realized it.
I believe your only option is to increase the delay. I don’t think it’s possible to suppress the logging of individual events.
I put some additional comments here:
tell application "SuperDuper!"
try
delay 1
run using settings ("A>B/" & NamedFile) without user interaction
repeat while status is running
delay 12
end repeat
if status is done then
(* HERE IS A DOUBLE TELL! *)
tell application "SuperDuper!" to quit
delay 2
(* IS THIS THE PROBLEM DIALOG ? *)
(* IT'S IN A TELL BLOCK FOR APP THAT JUST QUIT! *)
(* TRY SYSTEM EVENTS OR 'ME' *)
--display dialog NamedFile & " copied ..." giving up after 2
end if
on error errMsg
display dialog "Oops! ... " & errMsg
end try
end tell
As it happens I’m currently tinkering with a script to do that in another app. This might get you started:
set checkLines to (read (POSIX file "/path/to/log"))'s paragraphs -10 thru -1
Thanks for the clues - Now I can read the completion status this way for a specific SuperDuper logfile:
set pathtolog to "~/Library/Application Support/SuperDuper!/Saved Settings/A>B/03 DataA>B.sdsp/Logs/2011-11-18 13:56:30 -0800.sdlog"
if (read pathtolog from -17 to -5) is "Copy complete" then display dialog "Good!"
but I’m still struggling to constructing the variable path to the latest log, including that the logs are contents rather than just visible hierarchy …
set NamedFile to (name of item i of FileList)-- path of actual settings file you already have
set logFolder to ((item i of FileList as text) & "Logs:") as alias
set thisLog to last file of logFolder whose kind is "Log File"
“Logs” is the only folder in a settings package, AFAICT.
“last file” returns what Finder thinks is the last file in its own (sometimes peculiar) sort order. Having the date in the name makes it work here.
“Kind” is from the Get Info window. It might be localised, so check before using.
Console can open those logfiles, but they’re actually in RTF format.
Reading them in AppleScript means you may have to take some RTF formatting into consideration.
Thanks for the ideas guys. I have successfully gotten the script to read the latest log success for a given Settings file:
ExamineLatestLogFile.scpt
tell application "Finder"
set LogFilesInSettingsFile to POSIX file "/Users/acellier/Library/Application Support/SuperDuper!/Saved Settings/C-X/01 DataC-X.sdsp/Logs" as alias
set LogFileList to every file in LogFilesInSettingsFile
set logcount to (number of items in LogFileList) as integer
--display dialog logcount & " items in the log file list at:" & "
--" & "
--" & LogFilesInSettingsFile as string
set chosenFileName to (name of item (logcount - 1) of LogFileList)
set chosenFilePath to (LogFilesInSettingsFile & chosenFileName) as string
set chosenFilePath to chosenFilePath as alias
if (read chosenFilePath from -17 to -5) is "Copy complete" then set BackupResult to "Backup Completed OK!"
if (read chosenFilePath from -17 to -5) is not "Copy complete" then set BackupResult to "Not a backup!"
(* main display begin*)
display dialog logcount & " items in the log file list ..." & "
" & ("Latest Log File is Named: " & "
" & chosenFileName as string) & "
Log File Path is: " & chosenFilePath & "
" & "
Creation date: " & "
" & creation date of (chosenFilePath as alias) & "
" & "
BackupResult: " & BackupResult as string
(* main display end*)
end tell
But I’m hung up trying to use this as the core of a script to scan thru ALL of the settings files in a given folder - the same code that works in the first is sticking in the larger context:
ExamineAllLatestLogFiles.scpt
tell application "Finder"
set Settingsfolder to POSIX file "/Users/acellier/Library/Application Support/SuperDuper!/Saved Settings/C-X/" as alias
set SettingsFileList to every file in Settingsfolder
set SettingsFileCount to (number of items in SettingsFileList) as integer
display dialog (Settingsfolder & "
" & "
" & SettingsFileCount & " items in list
" & name of items of Settingsfolder & " ") as text
repeat with i from 1 to SettingsFileCount -- number of backup settings
set NamedSettingsFile to (name of item i of SettingsFileList) -- go thru Settings one by one
--display dialog NamedFile giving up after 3
set LogFolderPath to Settingsfolder & NamedSettingsFile & ":Logs" as string
--display dialog "Log folder location: " & LogFolderPath
set LogFileList to every file in (LogFolderPath as alias) -- list the log files
set logcount to (number of items in LogFileList) as integer -- count the log files
display dialog logcount & " items in the log file list at:" & "
" & "
" & LogFolderPath as string
--display dialog (number of items in LogFileList & " items in the log file list") as string
set chosenFileName to (name of item (logcount - 1) of LogFileList)
set chosenFilePath to (LogFolderPath & chosenFileName) as string
--display dialog chosenFilePath
set chosenFilePath to file chosenFilePath --BAD
if (read chosenFilePath from -17 to -5) is "Copy complete" then set BackupResult to "Backup Completed OK!"
if (read chosenFilePath from -17 to -5) is not "Copy complete" then set BackupResult to "Not a backup!"
(* main display begin*)
display dialog ("Latest Log File is Named: " & "
" & chosenFileName as string) & "
Latest Log File Path is: " & chosenFilePath & "
" & "
Creation date: " & "
" & creation date of (chosenFilePath as alias) & "
" & "
BackupResult: " & BackupResult as string
(* main display end*)
end repeat
end tell
(*
Result:
error "Finder got an error: Can't get file \"OSX6A:Users:acellier:Library:Application Support:SuperDuper!:Saved Settings:C-X:01 DataC-X.sdsp:Logs2011-10-03 18/35/23 -0700.sdlog\"." number -1728 from file "OSX6A:Users:acellier:Library:Application Support:SuperDuper!:Saved Settings:C-X:01 DataC-X.sdsp:Logs2011-10-03 18/35/23 -0700.sdlog"
*)
Look again; there’s no colon after “Logs”.
This is the line which needs an edit:
set LogFolderPath to Settingsfolder & NamedSettingsFile & ":Logs" as string
That’s not a folder path…
Unsolicited advice: you are using actual returns when formatting messages. This makes edits harder, IMO.
I would use “… & return & …”, so the returns are in plain sight. Personal preference, of course.
set LogFileList to every file in LogFilesInSettingsFile
.
.
set chosenFileName to (name of item (logcount - 1) of LogFileList)
The first line lists everything, including the .diagnostics files, which you do not want to see.
In the second line you get the last-but-one item, as the last one is a .diagnostics file.
You do not need to get all files in the log folder, just to get the last log file:
set chosenFilePath to last file of LogFilesInSettingsFile whose kind is "Log File"
In this way Finder does all the work, which is usually faster than doing it in the script. It also eliminates counting the files.
if (read chosenFilePath from -17 to -5) is "Copy complete" then set BackupResult to "Backup Completed OK!"
if (read chosenFilePath from -17 to -5) is not "Copy complete" then set BackupResult to "Not a backup!"
Can be rewritten as
if (read chosenFilePath from -17 to -5) is "Copy complete" then
set BackupResult to "Backup Completed OK!"
else-- not a backup log, or backup went wrong
set BackupResult to "Not a backup!"
end if
OK! Thank you very much for the suggestions. Here is a working script to examine a folder of SuperDuper! Settings files and determine the completion of the latest backup attempt. And it even caught one from yesterday that had completed with an error!
tell application "Finder"
set Settingsfolder to POSIX file "/Users/User1/Library/Application Support/SuperDuper!/Saved Settings/A>B/" as alias
set SettingsFileList to every file in Settingsfolder
set SettingsFileCount to (number of items in SettingsFileList) as integer
display dialog (SettingsFileCount & " Settings files in the folder at:" & return & return & Settingsfolder & return & return & "Settings files in the list: " & return & name of items of Settingsfolder) as text
repeat with i from 1 to SettingsFileCount -- number of backup settings
set NamedSettingsFile to (name of item i of SettingsFileList) -- go thru Settings one by one
set LogFolderPath to Settingsfolder & NamedSettingsFile & ":Logs:" as string
set chosenFileName to (name of (last file of folder named LogFolderPath whose kind is "Log File"))
set chosenFilePath to (last file of folder named LogFolderPath whose kind is "Log File") as alias
if (read chosenFilePath from -17 to -5) is "Copy complete" then
set BackupResult to "Backup Completed OK!"
else --if (read chosenFilePath from -17 to -5) is not "Copy complete" then
set BackupResult to "Not a backup!"
end if
display dialog "Backup no. " & i & " of " & SettingsFileCount & " ..." & return & return & "Settings: " & NamedSettingsFile & return & return & "BackupResult: " & BackupResult & return & return & "Creation date:" & return & creation date of chosenFilePath & return & return & "Latest Log File is Named: " & return & chosenFileName & return & return & "Latest Log File Path is: " & chosenFilePath
end repeat
end tell
One more question - the first display dialog is a bit hard to read because the settings files are all jammed together like a run-on sentence. How can I make the filenames simply appear each on a new line?
tell application "Finder"
set Settingsfolder to POSIX file "/Users/acellier/Library/Application Support/SuperDuper!/Saved Settings/A>B/" as alias
set SettingsFileList to every file in Settingsfolder
set SettingsFileCount to (number of items in SettingsFileList) as integer
display dialog (SettingsFileCount & " Settings files in the folder at:" & return & return & Settingsfolder & return & return & "Settings files in the list: " & return & name of items of Settingsfolder) as text
...
Now I returned to the originally posted script, for a sequence of SuperDuper! backups using the set of Settings.sdsp files in a stated folder - I’ve incorporated the completeness check from above as an in-process dialog, and as a log file written to the desktop for post-review. Further comments are very welcome!
tell application "Finder"
set Settingsfolder to POSIX file "/Users/acellier/Library/Application Support/SuperDuper!/Saved Settings/A>B/" as alias
set FileList to every file in Settingsfolder
display dialog ("Settings Folder location: " & return & return & Settingsfolder & return & return & (number of items in FileList & " items in list") & return & return & name of items of Settingsfolder & return & return & "Power Up the Backup Drive 'B' before running!") as text
if (not (exists disk "DataB")) then
display dialog "PLEASE mount the backup drive!"
quit
end if
repeat with i from 1 to number of items in FileList
set NamedFile to (name of item i of FileList)
tell application "SuperDuper!"
try
run using settings ("A>B/" & NamedFile) without user interaction
repeat while status is running
delay 15
end repeat
if status is done then
tell application "SuperDuper!" to quit
delay 2
end if
on error errMsg
display dialog "Oops! ... " & errMsg
end try
end tell
delay 5
tell application "Finder"
set LogFolderPath to Settingsfolder & NamedFile & ":Logs:" as string
set chosenFileName to (name of (last file of folder named LogFolderPath whose kind is "Log File") as string)
set chosenFilePath to (last file of folder named LogFolderPath whose kind is "Log File") as alias
if (read chosenFilePath from -17 to -5) is "Copy complete" then
set BackupResult to "Backup Completed OK!"
else
set BackupResult to "Not a backup!"
end if
activate me
display dialog NamedFile & return & return & "BackupResult: " & return & BackupResult & return & return & "Creation date: " & return & creation date of (chosenFilePath) & return & return & "Latest Log File is Named: " & return & chosenFileName & return & return & "Log File Path is: " & chosenFilePath giving up after 3
set newtext to (return & NamedFile & return & "BackupResult: " & BackupResult & return & "Creation date: " & return & creation date of (chosenFilePath) & return) as string
tell me to AppendToDesktopLogFile("Backup.logtxt", newtext)
end tell
end repeat
end tell
activate me
with timeout of 43200 seconds -- 12 hours
display dialog ("Back ups All Complete !! & return & Dismount & Power down the backup drive 'X'")
end timeout
end
on AppendToDesktopLogFile(filename, newtext)
(* Warning: filename must not end in ".log" or else a "file already open" error will result. Maybe some system logging daemon takes over all .log files?? Some stupid bug in AppleScript? *)
set filePath to (path to desktop as string) & filename
set fileRef to open for access filePath with write permission
set newtext to (return & return & (current date) & ": " & newtext) as string
write newtext to fileRef starting at eof
close access fileRef
end AppendToDesktopLogFile
One remaining glitch is an error message like the following, which happens just before SuperDuper! gets told to run, but only on the second and all subsequent runs of the settings file list loop (does not happen on the first call to SD!):
Events/Replies: …
tell application “AppleScript Editor”
«event SdPrRunn» without «class noUI» given «class filE»:“A>B/04 PhotA>B.sdsp”
end tell
tell application “SuperDuper!”
run using settings “A>B/04 PhotA>B.sdsp” without user interaction
…
The ‘name of items of Settingsfolder’ is a list. A list-as-text is one line. Here’s a bit of code to turn a list into separate lines for a dialog:
set names to {"n1", "n2", "n3", "n4"}
set AppleScript's text item delimiters to return
set names to names as text
set AppleScript's text item delimiters to ""
names
Try it, and see the result in the event panel.
You say “error message”, but the script actually finishes? Then it’s not an error! But anyways…
It looks like that SuperDuper command is directed at the Editor after the first run. Not sure why, but I see you still have several nested tell blocks - the entire script is in a Finder tell, but inside that one there’s 2 tell blocks for SD, and one for Finder. I think you should un-nest or eliminate them, and see what happens. The ‘tell SD to quit’ is redundant, just ‘quit’ will do. Basically, when done telling Finder you should ‘end tell’, and start telling SD until done with SD.
Also, there’s ‘activate me’ without a tell. Looks very suspicious. I’ve never see a plain ‘end’ in a working script before, it’s always ‘end ’. Change to “tell me to display dialog…”