backup multiple partitions with SuperDuper!

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 can do this on its own.
Why the script?

Thanks for asking.

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

On my machines the path to the log is ‘~/Library/Application Support/SuperDuper!/Scheduled Copies/Smart Update to-disk-name from-disk-name.sdsp/Logs/’

The current log is the second last (-2) document.

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"
*)

I hope this isn’t too lengthy …

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.

More unsolicited advice :slight_smile:

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…”