Copy shared tracks, ctd

Now where were we?

We've collected the selected shared tracks in sel and have set the login variables for secure operations to come. Now to process the tracks; get their locations in order to scp them from the remote machine to the local machine.

(And before I forget: right after calling get_login_info(), set your music folder variables, locMusicLibrary and remMusicLibrary, with the get_local_music_folder() and get_remote_music_folder() handlers.)

The thing is, a shared track doesn't have a location property. In order to get its location, first get its persistent ID and then ask the remote iTunes for the location of a track in its library with that persistent ID. Once we have that file path, we can set up the other requisite file and folder paths similarly to the way we did for the previous script.

tell application "iTunes"
	repeat with t in sel
			my copy_this_file_by_pid(get t's persistent ID)
		end try
	end repeat
end tell

-- put with other handlers:
to copy_this_file_by_pid(pid)
	-- 1:
	set osaCom to quoted form of ¬
		("osascript -e 'tell application\"iTunes\" to return POSIX path of (get location of some track of library playlist 1 whose persistent id is\"" & pid & "\")'")
	set posixLoc to do shell script ("ssh " & remAddr & space & osaCom)
	(*/Volumes/Media/iTunes Media/Status Quo/Ma Kelly's Greasy Spoon/01 Spinning Wheel Blues.mp3*)
	-- 2:
	set fileFolderHeirarchy to text ((offset of remMusicLibrary in posixLoc) + (length of remMusicLibrary)) thru -1 of posixLoc
	(*Status Quo/Ma Kelly's Greasy Spoon/01 Spinning Wheel Blues.mp3*)
	-- 3:
	set locLoc to (locMusicLibrary & fileFolderHeirarchy) as text
	(*/Users/dougadams/Music/iTunes/iTunes Music/Status Quo/Ma Kelly's Greasy Spoon/01 Spinning Wheel Blues.mp3*)
	-- 4:
	set locContainer to (my list_to_text(items 1 thru -2 of my text_to_list(locLoc, "/"), "/") & "/") as text
	(*/Users/dougadams/Music/iTunes/iTunes Music/Status Quo/Ma Kelly's Greasy Spoon/*)
	-- to be continued...

(The file used as an example is located in an iTunes Music folder on an external drive mounted on the remote machine. Also, my apologies from letting the code run across the screen but a continuation character can't be used to much avail here.)

The handler is passed the persistent ID of each track on each repeat loop. Note the try block around the handler call will prevent errors from stopping progress.

-- 1: an osascript is ssh'd to the remote user and retrieves the POSIX file path of the particular track's location as posixLoc.

-- 2: the variable fileFolderHeirarchy is set to the artist/album/file path. It is created by retrieving the rest of the file path that appears after the remote iTunes Music folder path remMusicLibrary.

-- 3: the locLoc (my shorthand for "local location") is set to the path the file will have after it is copied to the local machine. It is a concatenation of the locMusicLibrary string and the fileFolderHeirarchy string just obtained. This is the string that will be needed to add the file to the local iTunes.

-- 4: the locContainer 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 local machine. Add this handler with the others:

on loc_file_exist(locLoc)
		set x to do shell script "test -e \"" & locLoc & "\""
		return (x is "")
	on error
		return false
	end try
end loc_file_exist

...or you could use an exists routine with System Events, or whatever. As long as the handler returns true or false.

And here is the rest of the copy_this_file_by_pid() handler:

	if not my loc_file_exist(locLoc) then
		-- 5: == containing folders (artist/album/) exists? if not, create
		set mkdirCom to ("mkdir -p " & my escape_special_chars(locContainer)) as text
			set x to do shell script mkdirCom
			log x -- this result not needed; observation/debugging only
		on error m
			log ("mkdir err: " & m)
		end try
		-- 6: == copy the file to the local user's iTunes Music folder
		set scpCom to ("scp -EC" & space & remAddr & ":" & ¬
			quoted form of my escape_special_chars(posixLoc) & space & ¬
			quoted form of locContainer) as text
		set rez to do shell script scpCom
		log rez -- this result not needed; observation/debugging only
		-- 7: == add the newly copied file to iTunes
			set aliasToAdd to (POSIX file (locLoc)) as text
			with timeout of (1 * days) seconds
				tell application "iTunes"
					-- add the file
					set newTrack to add alias aliasToAdd
				end tell
			end timeout
		on error m number n
			log m
			log n
		end try
		log "EXISTS - SKIP"
	end if
end copy_this_file_by_pid

Once again we have to contend with a Klein bagel of an escaping issue. Include this escape_special_chars() handler with the other handlers:

to escape_special_chars(n)
	set escThese to " &()'"
	repeat with chr in escThese
		set n to my replace_chars(n, chr, ("\\" & chr) as text)
	end repeat
	return n
end escape_special_chars

This handler will escape spaces, ampersands (&'s), and parentheses where required. There may be other special characters that need to be escaped for mkdir and scp but these were the only ones I encountered when operating in this direction.

-- 5: create intermediate "Artist" and/or "Album" folders if they do not yet exist in the local iTunes Music folder. If the folders do exist, mkdir fails silently without an error.

-- 6: scp the file over.

-- 7: Convert the locLoc file path for iTunes and add it to iTunes as an alias. Note that I have set the result of the add command to the newTrack variable--we'll use it in a mod later.

A full listing of this script is 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.