Send selected manually, ctd.

  • The process_this_file() handler

The script has to emulate the tasks we were able to do before with the two rsync and perl routines: check if the selected track's file already exists at the destination, supply a destination file path; perform the file copy to the destination. We have already used a routine that can add a file to a remote iTunes and we'll only need to slightly modify that for this script.

First we need to format some file paths based on the POSIX location path passed to the handler:

-- == handlers = == == == == == == == 

-- copy to remote iTunes and add
to process_this_file(posixLoc)
	log posixLoc
	(*/Users/dougadams/Music/iTunes/iTunes Music/Little Feat/Feats Don't Fail Me Now/05 Spanish Moon.m4a*)
	-- == init some variables
	-- 1:
	set fileFolderHeirarchy to text ((length of locMusicLibrary) + 1) thru -1 of (posixLoc as text)
	(*Little Feat/Feats Don't Fail Me Now/05 Spanish Moon.m4a*)
	-- 2:
	set remLoc to (remMusicLibrary & fileFolderHeirarchy) as text
	(*/Users/cleanuser/Music/iTunes/iTunes Music/Little Feat/Feats Don't Fail Me Now/05 Spanish Moon.m4a*)
	-- 3:
	set remContainer to (my list_to_text(items 1 thru -2 of my text_to_list(remLoc, "/"), "/") & "/") as text
	(*/Users/cleanuser/Music/iTunes/iTunes Music/Little Feat/Feats Don't Fail Me Now/*)
	-- to be continued...
end process_this_file

(I purposely chose a track with an apostrophe in its file path so I could smoke-test the upcoming escaping and quoting routines.)

The handler is passed the POSIX version of a track's location as the variable posixLoc. Here are the file paths we need:

-- 1: the variable fileFolderHeirarchy is set to the artist/album/file path, which is what rsync's dry-run routine would have supplied. It is created by retrieving the rest of the file path that appears after the local iTunes Music folder path (offset of the length of the locMusicLibrary string plus one position to the right through the last character--you made locMusicLibrary a global up top, right?)

-- 2: remLoc is set to the path the file will have after it is copied to the remote machine. It is a concatenation of the remMusicLibrary string (you made it a global, too, right?) and the fileFolderHeirarchy string just obtained. This is the string that the osascript needs to add the file to the remote iTunes.

-- 3: the remContainer variable is the path to the file's (eventual) containing folder. This will be the destination path used when we scp the file.

Next, we need to determine if the selected file already exists on the remote machine. Add this handler with the others:

on rem_file_exists(remF)
	set testCom to quoted form of ("test -e \"" & remF & "\"")
		set x to (do shell script ("ssh " & remAddr & space & testCom))
		return (x is "")
	on error
		return false
	end try
end rem_file_exists

If the result of the test command is anything but an empty string (technically, it would be the number--not the string--"0", but AppleScript coerces the number 0 to empty string) then return false. We are rooting for a false result so we can copy the file. Otherwise, we will skip this track.

Now include the fix_single_quotes() handler from earlier as well as this additional handler to escape spaces and single quotes:

to escape_for_unix(n)
	set n1 to my replace_chars(n, " ", "\\ ")
	return my replace_chars(n1, "'", "\\'")
end escape_for_unix

Here is the rest of the process_this_file() handler:

	if not my rem_file_exists(remLoc) then
		-- 4: == containing folder exists? if not, create
		set mkdirCom to quoted form of ("mkdir -p " & my escape_for_unix(remContainer)) as text
		-- mkdir will error quietly if the containing folders already exist
			set x to do shell script "ssh " & remAddr & space & mkdirCom
			log x
		on error m
			log ("mkdir err: " & m)
		end try
		-- 5: == copy the file
		set scpCom to ("scp -EC" & space & quoted form of posixLoc & space & ¬
			remAddr & ":\"" & my escape_for_unix(remContainer) & "\"") as text
		set rezList to do shell script scpCom
		log rezList -- this result not needed; observation only
		-- 6: == add the newly copied file to remote iTunes
		set fileToAdd to my fix_single_quotes(remLoc)
			with timeout of (1 * days) seconds
				set osaCom to quoted form of ¬
					("osascript -e 'tell application\"iTunes\" to add POSIX file \"" & fileToAdd & "\"'")
				do shell script ("ssh " & remAddr & space & osaCom)
			end timeout
		on error m number n
			log m
			log n
		end try
		log "EXISTS - SKIP"
	end if
end process_this_file

-- 4: if the location indicated by remContainer doesn't exist create it with mkdir. The p flag tells mkdir to create any intermediate folders that don't exist yet either, so we'll be certain to have a artist/album folder "receiver" on the remote end. If, however, the folder path already does exist, mkdir will fail silently and exit the try block without attempting to re-create the folder path. (but each time? yes, because tracks may each have different artist and album paths)

-- 5: copy the file with scp. The format for scp is similar to cp where source is the track's file path on the local end and destination is the remContainer folder on the remote end:

scp options source destination

and like rsync the ":" tells scp to use an ssh-type secure login. Figuring out the escapes here was mind-blowing (but you ain't seen nothin' yet). The -E and -C flags handle extended attributes and enable ssh compression, respectively.

-- 6: this is the routine used with the filesToAdd list earlier but without the trackAddedCounter business. (Although you could do something similar to report if files did/didn't get added, you know?)

The full script is listed on the next page.


Get More Information:

See the man pages for:

Apple's Technical Note TN2065 should be read by anyone who uses do shell script, with especial regard to string quoting and escaping.

Site contents © 2001 - 2021 (that's right: 2001) Doug Adams and weblished by Doug Adams. Contact support AT dougscripts DOT com. About.
All rights reserved. Privacy.
AppleScript, iTunes, iPod, iPad, and iPhone are registered trademarks of Apple Inc. This site has no direct affiliation with Apple, Inc.
The one who says "it cannot be done" should not interrupt the one doing it.