Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
I would like to make an iTunes auto-tagging script. Basically, what it does is this:
  1. Loop through all the selected songs
  2. Find each song file on my computer (in the form filename.ext) - the song names in iTunes contain the original extension so I know what to search for
  3. Get the containing folder of the song file and set that to the song's Album tag
  4. Get the containing folder of the containing folder of the song file and set that to the song's Artist tag

Can anyone here point me in the right direction? What I'm struggling with is figuring out how to search for a file on my computer with AppleScript, then do something with the search result (there should only be one result - I could guarantee that by limiting the search to only the folder of interest, but again, I'm not sure how).
 

HexMonkey

Administrator emeritus
Feb 5, 2004
2,240
504
New Zealand
Is this what you want? Rather than searching for the song file, it just gets the file reference from iTunes.

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		set trackPath to location of nextTrack
		tell application "Finder"
			set trackFile to file trackPath
			
			--Get container names
			set theContainer to container of trackPath
			set albumName to name of theContainer
			set artistName to name of container of theContainer
		end tell
		
		--Set track information
		set album of nextTrack to albumName
		set artist of nextTrack to artistName
	end repeat
end tell
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
HexMonkey said:
Is this what you want? Rather than searching for the song file, it just gets the file reference from iTunes.

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		set trackPath to location of nextTrack
		tell application "Finder"
			set trackFile to file trackPath
			
			--Get container names
			set theContainer to container of trackPath
			set albumName to name of theContainer
			set artistName to name of container of theContainer
		end tell
		
		--Set track information
		set album of nextTrack to albumName
		set artist of nextTrack to artistName
	end repeat
end tell
This is good. The only problem is this:

Let's say the music files in iTunes are located in ~/Music/iTunes/iTunes Music and the original source files are in ~/Music/Source/Module. The file we're interested in is called Stream.s3m.

What I want is not ~/Music/iTunes/iTunes Music/(artist)/(album)/Stream.s3m but rather ~/Music/Source/Module/(other folders go here)/(artist)/(album)/Stream.s3m - where the names of the second artist and album folders contain the data to add to the iTunes track. I'm not entirely sure if your script retrieves the right file, but I'll have to test it.
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
OK, I tested it. It writes the tags correctly, but it's not getting the tag info from the right file. It's getting it from the folder of the iTunes track, which is no help at all (it will always tag it Unknown Artist and Unknown Album).

EDIT: The problem seems to be in the section I've highlighted:

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		[COLOR="Red"][B]set trackPath to location of nextTrack[/B][/COLOR]
		tell application "Finder"
			set trackFile to file trackPath
			
			--Get container names
			set theContainer to container of trackPath
			set albumName to name of theContainer
			set artistName to name of container of theContainer
		end tell
		
		--Set track information
		set album of nextTrack to albumName
		set artist of nextTrack to artistName
	end repeat
end tell
trackPath isn't getting set to the right file.
 

mduser63

macrumors 68040
Nov 9, 2004
3,042
31
Salt Lake City, UT
I really don't think there's a simple way to do what you're asking with AppleScript. You need a script that does a system-wide search (or at least a search within some set of folders) and can determine on it's own which file corresponds to which song, when they're not linked in the iTunes library itself. There are tools out there that will tag files based on the folder hierarchy that they're contained in. You would probably be best off using one of those, and then after all your files are tagged, import them into iTunes.
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
I got it to work, sort of:

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		set trackName to name of nextTrack
		set trackName to replace_chars(trackName, "'", "\\'")
		set the_command to ("mdfind -onlyin ~/Music/Source/Module " & trackName) as string
		set returned_list to (do shell script the_command)
		
		if returned_list is not "" then -- we got some results
			-- make a list from the string; items are separated by carriage returns
			set new_list to text_to_list(returned_list, return)
			repeat with trackFile in new_list
				set trackFile to POSIX file trackFile
				tell application "Finder"
					--Get container names
					set theContainer to container of trackFile
					set albumName to name of theContainer
					set artistName to name of container of theContainer
				end tell
			end repeat
		end if
		
		--Set track information
		set album of nextTrack to albumName
		set artist of nextTrack to artistName
	end repeat
end tell

on replace_chars(txt, srch, repl)
	set AppleScript's text item delimiters to the srch
	set the item_list to every text item of txt
	set AppleScript's text item delimiters to the repl
	set txt to the item_list as string
	set AppleScript's text item delimiters to ""
	return txt
end replace_chars

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list

When I run this I get an error: "iTunes got an error: Can't continue replace_chars." I can't figure out why, since it works perfectly in the sample script here: http://www.dougscripts.com/itunes/itinfo/spotlight.php

Scroll down to where it says:
OK, that's fine, but there's a coupla things:
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
Found the cause of the above problem and fixed it. However, it still doesn't work.

Script:

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		set trackName to name of nextTrack
		set trackName to my replace_chars(trackName, "'", "\\'")
		set the_command to ("mdfind -onlyin ~/Music/Source/Module " & "'kMDItemFSName == " & trackName & "'") as string
		set returned_list to (do shell script the_command)
		
		if returned_list is not "" then -- we got some results
			-- make a list from the string; items are separated by carriage returns
			set new_list to my text_to_list(returned_list, return)
			repeat with this_file in new_list
				set trackFile to POSIX file this_file
				tell application "Finder"
					
					--Get container names
					set theContainer to container of trackFile
					set albumName to name of theContainer
					set artistName to name of container of theContainer
				end tell
			end repeat
		end if
		
		--Set track information
		set album of nextTrack to albumName
		set artist of nextTrack to artistName
	end repeat
end tell

on replace_chars(txt, srch, repl)
	set AppleScript's text item delimiters to the srch
	set the item_list to every text item of txt
	set AppleScript's text item delimiters to the repl
	set txt to the item_list as string
	set AppleScript's text item delimiters to ""
	return txt
end replace_chars

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list

Event Log:
Code:
tell application "iTunes"
	get selection
		{file track id 4483 of folder playlist id 3505 of source id 39}
	get name of file track id 4483 of folder playlist id 3505 of source id 39
		"Stream.xm"
	do shell script "mdfind -onlyin ~/Music/Source/Module 'kMDItemFSName == Stream.xm'"
		"/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm"
	get POSIX file "/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm"
		"iTunes got an error: Can't get POSIX file (item 1 of {\"/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm\"})."

This has me completely baffled.
 

mduser63

macrumors 68040
Nov 9, 2004
3,042
31
Salt Lake City, UT
wrldwzrd89 said:
Code:
tell application "iTunes"
	get selection
		{file track id 4483 of folder playlist id 3505 of source id 39}
	get name of file track id 4483 of folder playlist id 3505 of source id 39
		"Stream.xm"
	do shell script "mdfind -onlyin ~/Music/Source/Module 'kMDItemFSName == Stream.xm'"
		"/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm"
	get POSIX file "/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm"
		"iTunes got an error: Can't get POSIX file (item 1 of {\"/Users/wrldwzrd89/Music/Source/Module/single song/XM/CyberZip/Nebula/Stream.xm\"})."

This has me completely baffled.

Try taking the 'set trackFile to POSIX file this_file' line and putting it inside the Finder tell. BTW, I'm impressed that you've gotten as far as you have using AppleScript. I had forgotten that Spotlight could be accessed via the command line.
 

wrldwzrd89

macrumors G5
Original poster
Jun 6, 2003
12,110
77
Solon, OH
mduser63 said:
Try taking the 'set trackFile to POSIX file this_file' line and putting it inside the Finder tell. BTW, I'm impressed that you've gotten as far as you have using AppleScript. I had forgotten that Spotlight could be accessed via the command line.
Tried that, got the exact same error, but in Finder instead of in iTunes. :confused:
 

mduser63

macrumors 68040
Nov 9, 2004
3,042
31
Salt Lake City, UT
wrldwzrd89 said:
Tried that, got the exact same error, but in Finder instead of in iTunes. :confused:

I'm a little curious about the escaped quotes around the file path. I'm not an AppleScript expert, but that just jumped out at me as something that could possibly cause a problem.
 

HexMonkey

Administrator emeritus
Feb 5, 2004
2,240
504
New Zealand
It works for me if I change the 'set trackFile to...' line to:
Code:
set trackFile to this_file as POSIX file

I also moved the 'set album...' and 'set artist...' lines so that the script wouldn't give an error if the search returned no results, and changed the 'set the_command to...' line to:
Code:
set the_command to ("mdfind -onlyin ~/Music/Source/Module " & "\"kMDItemFSName == '" & trackName & "*'\"") as string
which allows for multiple words in a filename and some text to follow the track name (eg the extension).

The modified code:

Code:
tell application "iTunes"
	--Get current track selection
	set theTracks to selection
	
	--Iterate through each track
	repeat with nextTrack in theTracks
		--Get the track's file path
		set trackName to name of nextTrack
		set trackName to my replace_chars(trackName, "'", "\\'")
		set the_command to ("mdfind -onlyin ~/Music/Source/Module " & "\"kMDItemFSName == '" & trackName & "*'\"") as string
		set returned_list to (do shell script the_command)
		--return returned_list
		if returned_list is not "" then -- we got some results
			-- make a list from the string; items are separated by carriage returns
			set new_list to my text_to_list(returned_list, return)
			repeat with this_file in new_list
				set trackFile to this_file as POSIX file
				tell application "Finder"
					
					--Get container names
					set theContainer to container of trackFile
					set albumName to name of theContainer
					set artistName to name of container of theContainer
				end tell
				
			end repeat
			--Set track information
			set album of nextTrack to albumName
			set artist of nextTrack to artistName
		end if
	end repeat
end tell

on replace_chars(txt, srch, repl)
	set AppleScript's text item delimiters to the srch
	set the item_list to every text item of txt
	set AppleScript's text item delimiters to the repl
	set txt to the item_list as string
	set AppleScript's text item delimiters to ""
	return txt
end replace_chars

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.