add songs from the Finder to your iTunes library

I recently had a bunch of songs in a folder that I wanted to add to my iTunes library. I knew a bunch of the songs were already in my library, but I also knew that the file names didn’t exactly match the name of the song that I already had in iTunes… so I wrote this script to help me add these files so I wasn’t adding a bunch of duplicates to my iTunes library. I thought others might find it useful. If you have any improvements let me know.

-- this script works on highlighted files in the frontmost Finder window

(*The purpose of this script is to aid you in adding songs from the Finder to your iTunes library. It does this by checking the words in the file names against the names of the songs in your iTunes library. It does not check for the exact file name, it checks for the individual words of the file name. This is done in an effort to get better search results from iTunes. Words in the file name that are 2 letters or less are ignored in the iTunes search. You can add specific characters or words to the "ignoredChars" list and they will be ignored in the search also. You should not have anything in the file names that would not be in the names of the songs in your iTunes library such as artist or album names, if you do you can add them to the ignoredChars list.*)

(*You are presented with a separate dialog box for each highlighted file. Each dialog box lists a highlighted song file and the songs from an iTunes search that closely match the file name. You then decide if you wish to add the song to your iTunes library.*)


set ignoredChars to {"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "-", "+", "=", "{", "}", "[", "]", "|", "\\", ":", ";", "\"", "<", ",", ">", ".", "?", "/", "mp3", "mp4", "m4a", "m4p", "the"} -- note: I left out an apostrophe from the list

set fileData to {}

tell application "Finder"
	set theSelection to the selection
end tell

-- this section takes the highlighted files in the Finder and scrubs data out of it to search itunes for matching songs
repeat with aFile in theSelection
	-- get the name and path of the selection
	set filePath to aFile as string
	set file_path to filePath as list
	set fileName to name of (info for (aFile as alias))
	set file_name to fileName as list
	
	-- remove bad characters from the file name
	repeat with i from 1 to (count of ignoredChars)
		set fileName to replace_chars(fileName, item i of ignoredChars, " ")
	end repeat
	
	-- turn the file name into a list of search terms
	set wordList to the words of fileName
	
	-- remove words that are 2 characters or less from the search terms
	set modSearchTerms to {}
	repeat with aTerm in wordList
		if (count of aTerm) > 2 then
			set end of modSearchTerms to aTerm as string
		end if
	end repeat
	
	-- remove duplicate terms from the search terms
	set uniqueSearchTerms to removeDuplicates(modSearchTerms)
	
	-- compile a list of the file data, each list consists of: item 1 is the file name, item 2 is the file path, and the rest of the items are the search terms
	set end of fileData to file_name & file_path & modSearchTerms
end repeat

-- search itunes using the search terms
repeat with i from 1 to (count of fileData)
	set aSelection to item i of fileData
	set searchTerms to items 3 thru end of aSelection
	set itunes_songs to my searchItunes(searchTerms)
	
	-- present the dialog box where you decide if You want to add the song to iTunes
	if itunes_songs is {} then
		set addCheck to display dialog "No Songs in iTunes match the file:" & return & (item 1 of aSelection) & return & return & "Would you like to add this song to iTunes?" buttons {"Cancel", "No", "Yes"} default button "No"
		if button returned of addCheck is "Yes" then tell application "iTunes" to add (item 2 of aSelection) to library playlist 1
	else
		set AppleScript's text item delimiters to return
		set songDialog to itunes_songs as string
		set AppleScript's text item delimiters to ""
		set addCheck to display dialog "This song:" & return & (item 1 of aSelection) & return & return & "iTunes matches:" & return & songDialog & return & return & "Would you like to add this song to iTunes?" buttons {"Cancel", "No", "Yes"} default button "No"
		if button returned of addCheck is "Yes" then tell application "iTunes" to add (item 2 of aSelection) to library playlist 1
	end if
end repeat


--============subroutines ===================
on replace_chars(this_text, search_string, replacement_string)
	-- find/replace in text, from apple.com
	set astid to AppleScript's text item delimiters
	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 astid
	return this_text
end replace_chars

on removeDuplicates(a)
	-- removes duplicate items from a list
	script o
		property p : a
	end script
	set b to {}
	repeat with i from 1 to a's length
		tell o's p's item i to if ({it} is not in b) then set b's end to it
	end repeat
	return b
end removeDuplicates

on searchItunes(searchWords_list)
	-- searches iTunes and returns a list of "song name:artist name" that matches the search words
	-- the search words must be in list format
	-- this subroutine requires the "existsTerm" subroutine
	set a to {}
	-- get a list of names and artists of tracks from itunes with the first search term in it
	tell application "iTunes"
		launch
		set existingTracks to (tracks of library playlist 1 whose name contains (item 1 of searchWords_list))
		repeat with i from 1 to count of existingTracks
			set thename to (name of item i of existingTracks)
			set theArtist to (artist of item i of existingTracks)
			set end of a to thename & " by " & theArtist
		end repeat
	end tell
	-- remove list items from above that don't have other search terms in them
	set b to a
	repeat with i from 2 to (count of searchWords_list)
		set theterm to item i of searchWords_list
		set subList to my existsTerm(b, theterm)
		set b to subList
	end repeat
	return b
end searchItunes

on existsTerm(theList, searchTerm)
	-- iterates through a list and only returns list items that contain the search term
	set newList to {}
	repeat with i from 1 to (count of theList)
		set thisString to item i of theList
		set astid to AppleScript's text item delimiters
		-- separate the artist from the song
		set AppleScript's text item delimiters to " by "
		set a to the text items of thisString
		if item 1 of a contains searchTerm then
			-- put the song and artist back together
			set b to a as string
			set AppleScript's text item delimiters to astid
			set end of newList to b
		end if
	end repeat
	return newList
end existsTerm