- 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 try 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) try 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 try 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 try 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 else 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:
osascript
ssh
test
scp
mkdir
Apple's Technical Note TN2065 should be read by anyone who uses do shell script, with especial regard to string quoting and escaping.