SSH+rsync scripting

I’m sure there have been many scripts (or at least questions about scripts) that automate ssh so, for what it’s worth, I thought I’d give a script that I use for remote file transfers. This first script takes user input to create a custom AppleScript for each computer. Then, with user input, the second script creates a custom shell script for rsync over ssh file transfers. If you’ve never tried rsync, it’s a nice way to transfer lots of files/folders between computers quickly.

The second script can also be entered as an Automator workflow and attached to a hotkey. This is nice if you have lots of computers. Use something like +shift+1 for your first remote computer, +shift+2 for your second, etc.

Hope this is useful!

set Port22Query to display dialog "Are you using port 22?" buttons {"Cancel", "Yes", "No"}
if button returned of Port22Query is "No" then
	set escape to false
	repeat until escape is true
		beep
		set PortSelection to display dialog "Please enter your port number:" default answer "" & "80"
		set PortNum to text returned of PortSelection as Unicode text
		set PortCheck to display dialog "So this is the port for SSH?" & return & return & PortNum & return & return & "(make sure this is correct)" buttons {"Yes", "No"}
		if button returned of PortCheck is "No" then
			set escape to false
		else
			if button returned of PortCheck is "Yes" then
				set escape to true
			end if
		end if
	end repeat
else
	set PortNum to "22"
end if


set escape to false
repeat until escape is true
	beep
	set locationQuery to display dialog "Please enter your server's location:" default answer "" & "USERNAME@x.x.x.x"
	set serverLocation to text returned of locationQuery
	set oldTID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "@"
	set remote_userName to text item 1 of serverLocation
	set serverIP to text item 2 of serverLocation
	set AppleScript's text item delimiters to oldTID
	set theCheck to display dialog "So this is your server's location and Username?" & return & return & serverLocation & return & "Username:  " & remote_userName & return & return & "(make sure this is correct)" buttons {"Cancel", "Yes", "No"}
	if button returned of theCheck is "No" then
		set escape to false
	else
		if button returned of theCheck is "Yes" then
			set escape to true
		end if
	end if
end repeat
set remote_userName to my replace_chars(remote_userName, " ", "\\ ")

set buildFolder to (choose folder with prompt "Please select a location for your ssh script to go.") as alias
tell application "Finder"
	set buildFile to make new file at buildFolder with properties {name:"OSX Transfer.scpt"}
end tell
set buildFile to buildFile as text

set waitQuery to display dialog "Do you want a fully automated script with no SSH password prompt?" & return & return & "(make sure you've copied your public key onto the remote server before doing this)" buttons {"Yes", "No"}
if button returned of waitQuery is "No" then
	set theWait to "40"
else
	set theWait to "25"
end if


set the_text to "set theExoticCharacters to {\" \",\"'\", \"\\\"\", \";\", \":\",\"*\"} --expand this list if needed
set theNormalCharacters to {\"\\\\ \", \"\\\\'\", \"\\\\\\\"\", \"\\\\;\", \"\\\\:\",\"\\\\*\"} --corrects characters for Terminal

set directionQuery to display dialog \"Will you pull files or push files?\" buttons {\"Pull\", \"Push\", \"Cancel\"}
set directionChoice to button returned of directionQuery

if directionChoice is \"Push\" then
	set itemQuery to display dialog \"Are you moving a file or folder?\" buttons {\"Cancel\", \"File\", \"Folder\"}
	set itemType to button returned of itemQuery
	if itemType is \"Folder\" then
		set this_item to (choose folder with prompt \"select your folder to move\")
	else
		if itemType is \"File\" then
			set this_item to (choose file with prompt \"select your files to move\")
		end if
	end if
	set file_path to (POSIX path of this_item)
	
	set escape to false
	repeat until escape is true
		set pathQuery to display dialog \"Please enter the path to drop the the file on your server\" default answer \"\" & \"~/Desktop\"
		set pathLoc to text returned of pathQuery
		set pathCheck to display dialog \"So this is the path?\" & return & return & pathLoc & return & return & \"(make sure this is correct)\" buttons {\"Cancel\", \"Yes\", \"No\"}
		if button returned of pathCheck is \"no\" then
			set escape to false
		else
			if button returned of pathCheck is \"yes\" then
				set escape to true
			end if
		end if
	end repeat
	
else
	set escape to false
	repeat until escape is true
		set pathQuery to display dialog \"Please enter the path to the file you want on the server\" default answer \"\" & \"~/Desktop\"
		set pathLoc to text returned of pathQuery
		set pathCheck to display dialog \"So this is the path?\" & return & return & pathLoc & return & return & \"(make sure this is correct)\" buttons {\"Cancel\", \"Yes\", \"No\"}
		if button returned of pathCheck is \"no\" then
			set escape to false
		else
			if button returned of pathCheck is \"yes\" then
				set escape to true
			end if
		end if
	end repeat
	
	display dialog \"Select a folder to save the files from the server\"
	set this_item to (choose folder with prompt \"select drop folder\")
	set file_path to (POSIX path of this_item)
	
end if

set file_path to my renameFile(file_path)
set pathLoc to my renameFile(pathLoc)

activate application \"Terminal\"
tell application \"System Events\"
	tell process \"Terminal\"
		if directionChoice is \"Push\" then
		keystroke \"rsync -avze \\\"ssh -p 22\\\" \" & file_path & \" Edmundo@192.168.0.11:\\\"\" & pathLoc & \"\\\"\" & return
		delay " & theWait & "
	else
		keystroke \"rsync -avze \\\"ssh -p 22 \\\" Edmundo@192.168.0.11:\\\"\" & pathLoc & \"\\\" \\\"\" & file_path & \"\\\"\" & return
		delay " & theWait & "
		end if	
	end tell
	tell application \"Finder\" to quit application \"Terminal\"
end tell

-------------------------------------------------------------------
on renameFile(theName)
	global theExoticCharacters, theNormalCharacters
	set oldTID to AppleScript's text item delimiters
	repeat with i from 1 to count of theExoticCharacters
		set AppleScript's text item delimiters to item i of theExoticCharacters
		set theTextBits to text items of theName
		set AppleScript's text item delimiters to item i of theNormalCharacters
		set theName to theTextBits as text
	end repeat
	set AppleScript's text item delimiters to oldTID
	return theName
end renameFile"

set the open_buildFile to open for access file buildFile with write permission
write the_text to open_buildFile
close access the open_buildFile
display dialog "all done!"

-------------------------------------------------------------------
on replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

I’m a total idiot and uploaded the wrong script! Here is a version that actually works, sorry for not catching that before posting :frowning:

(* Script to handle rsync over ssh file transfers.  Change "theWait" varibale to adjust wait times to your preference.  Try generating child scripts for each of your computers, then package them as automator services and run them with hotkeys.
Ed Babcock (greenyouse)
8/16/2012
*)

set Port22Query to display dialog "Are you using port 22?" buttons {"Cancel", "Yes", "No"}
if button returned of Port22Query is "No" then
	set escape to false
	repeat until escape is true
		beep
		set PortSelection to display dialog "Please enter your port number:" default answer "" & "80"
		set PortNum to text returned of PortSelection as Unicode text
		set PortCheck to display dialog "So this is the port for SSH?" & return & return & PortNum & return & return & "(make sure this is correct)" buttons {"Yes", "No"}
		if button returned of PortCheck is "No" then
			set escape to false
		else
			if button returned of PortCheck is "Yes" then
				set escape to true
			end if
		end if
	end repeat
else
	set PortNum to "22"
end if


set escape to false
repeat until escape is true
	beep
	set locationQuery to display dialog "Please enter your server's location:" default answer "" & "USERNAME@x.x.x.x"
	set serverLocation to text returned of locationQuery
	set oldTID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "@"
	set remote_userName to text item 1 of serverLocation
	set serverIP to text item 2 of serverLocation
	set AppleScript's text item delimiters to oldTID
	set theCheck to display dialog "So this is your server's location and Username?" & return & return & serverLocation & return & "Username:  " & remote_userName & return & return & "(make sure this is correct)" buttons {"Cancel", "Yes", "No"}
	if button returned of theCheck is "No" then
		set escape to false
	else
		if button returned of theCheck is "Yes" then
			set escape to true
		end if
	end if
end repeat
set remote_userName to my replace_chars(remote_userName, " ", "\\ ")

set buildFolder to (choose folder with prompt "Please select a location for your ssh script to go.") as alias
tell application "Finder"
	set buildFile to make new file at buildFolder with properties {name:"OSX Transfer.scpt"}
end tell
set buildFile to buildFile as text

set waitQuery to display dialog "Do you want a fully automated script with no SSH password prompt?" & return & return & "(make sure you've copied your public key onto the remote server before doing this)" buttons {"Yes", "No"}
if button returned of waitQuery is "No" then
	set theWait to "40"
else
	set theWait to "25"
end if


set the_text to "set theExoticCharacters to {\" \",\"'\", \"\\\"\", \";\", \":\",\"*\"} --expand this list if needed
set theNormalCharacters to {\"\\\\ \", \"\\\\'\", \"\\\\\\\"\", \"\\\\;\", \"\\\\:\",\"\\\\*\"} --corrects characters for Terminal

set directionQuery to display dialog \"Will you pull files or push files?\" buttons {\"Pull\", \"Push\", \"Cancel\"}
set directionChoice to button returned of directionQuery

if directionChoice is \"Push\" then
	set itemQuery to display dialog \"Are you moving a file or folder?\" buttons {\"Cancel\", \"File\", \"Folder\"}
	set itemType to button returned of itemQuery
	if itemType is \"Folder\" then
		set this_item to (choose folder with prompt \"select your folder to move\")
	else
		if itemType is \"File\" then
			set this_item to (choose file with prompt \"select your files to move\")
		end if
	end if
	set file_path to (POSIX path of this_item)
	
	set escape to false
	repeat until escape is true
		set pathQuery to display dialog \"Please enter the path to drop the the file on your server\" default answer \"\" & \"~/Desktop\"
		set pathLoc to text returned of pathQuery
		set pathCheck to display dialog \"So this is the path?\" & return & return & pathLoc & return & return & \"(make sure this is correct)\" buttons {\"Cancel\", \"Yes\", \"No\"}
		if button returned of pathCheck is \"no\" then
			set escape to false
		else
			if button returned of pathCheck is \"yes\" then
				set escape to true
			end if
		end if
	end repeat
	
else
	set escape to false
	repeat until escape is true
		set pathQuery to display dialog \"Please enter the path to the file you want on the server\" default answer \"\" & \"~/Desktop\"
		set pathLoc to text returned of pathQuery
		set pathCheck to display dialog \"So this is the path?\" & return & return & pathLoc & return & return & \"(make sure this is correct)\" buttons {\"Cancel\", \"Yes\", \"No\"}
		if button returned of pathCheck is \"no\" then
			set escape to false
		else
			if button returned of pathCheck is \"yes\" then
				set escape to true
			end if
		end if
	end repeat
	
	display dialog \"Select a folder to save the files from the server\"
	set this_item to (choose folder with prompt \"select drop folder\")
	set file_path to (POSIX path of this_item)
	
end if

set file_path to my renameFile(file_path)
set pathLoc to my renameFile(pathLoc)

activate application \"Terminal\"
tell application \"System Events\"
	tell process \"Terminal\"
		if directionChoice is \"Push\" then
		keystroke \"rsync -avze \\\"ssh -p " & PortNum & "\\\" \" & file_path & \" " & serverLocation & ":\\\"\" & pathLoc & \"\\\"\" & return
		delay " & theWait & "
	else
		keystroke \"rsync -avze \\\"ssh -p " & PortNum & " \\\" " & serverLocation & ":\\\"\" & pathLoc & \"\\\" \\\"\" & file_path & \"\\\"\" & return
		delay " & theWait & "
		end if	
	end tell
	tell application \"Finder\" to quit application \"Terminal\"
end tell

-------------------------------------------------------------------
on renameFile(theName)
	global theExoticCharacters, theNormalCharacters
	set oldTID to AppleScript's text item delimiters
	repeat with i from 1 to count of theExoticCharacters
		set AppleScript's text item delimiters to item i of theExoticCharacters
		set theTextBits to text items of theName
		set AppleScript's text item delimiters to item i of theNormalCharacters
		set theName to theTextBits as text
	end repeat
	set AppleScript's text item delimiters to oldTID
	return theName
end renameFile"

set the open_buildFile to open for access file buildFile with write permission
write the_text to open_buildFile
close access the open_buildFile
display dialog "all done!"

-------------------------------------------------------------------
on replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars