script for fixing itunes pointing at duplicate track files

After messing up a migration of my iTunes library, I was left with many tracks in my library duplicated on disk
…/iTunes Music/Radiohead/OK Computer/01 Airbag.mp3
…/iTunes Music/Radiohead/OK Computer/01 Airbag 1.mp3
…/iTunes Music/Radiohead/OK Computer/02 Paranoid Android.mp3
…/iTunes Music/Radiohead/OK Computer/02 Paranoid Android 1.mp3
with iTunes using the later duplicate, the one with the " 1" prefix.

I made this script to iterate through all the iTunes library, find these tracks that point at these duplicate files, remap them back to the original files, then deletes the duplicate. A sanity check is made ensuring the duplicate is the same file size as the original before acting.

tell application "iTunes"
	set logcmd to "logger -t iTunesDupFix "
	repeat with x from 1 to count file tracks of library playlist 1
		set thistrack to file track x of library playlist 1
		if location of thistrack is missing value then
			--log x & " missing track - " & name of thistrack as text
			do shell script logcmd & "'" & x & " missing track: " & name of thistrack as text & "'"
		else
			
			set trackpath to location of thistrack as text
			
			set oldDelimiters to AppleScript's text item delimiters -- preserve original delimiters
			set AppleScript's text item delimiters to {":"}
			set pathcomponents to text items of trackpath
			set parentpath to (items 1 thru -2 of pathcomponents) as text
			set fullname to last item of pathcomponents
			
			set AppleScript's text item delimiters to {"."}
			set namecomponents to text items of fullname
			set barename to (items 1 thru -2 of namecomponents) as text
			set extension to last item of namecomponents
			set AppleScript's text item delimiters to oldDelimiters -- restore original delimiters
			
			if character -2 of barename is " " and character -1 of barename is "1" then
				set dupbarename to ((characters 1 thru -3 of barename)) as text
				set dupname to (dupbarename & "." & extension) as text
				set duppath to (parentpath & ":" & dupname) as text
				set doremap to false
				set dodelete to false
				tell application "Finder"
					if exists file trackpath then -- nested if's because this fails: (exists file x) and (exists file y)
						if exists file duppath then
							set tracksize to size of (info for file trackpath)
							set dupsize to size of (info for file duppath)
							if dupsize is equal to tracksize then
								set doremap to true
							else
								--log x & " not duplicate (file size " & dupsize & " vs " & tracksize & ") - " & trackpath
								do shell script logcmd & "'" & x & " not duplicate: " & POSIX path of duppath & "'"
							end if
						end if
					end if
				end tell
				if doremap then
					try
						set location of thistrack to duppath
						--log x & " updated - "& duppath
						do shell script logcmd & "'" & x & " updated: " & POSIX path of duppath & "'"
						set dodelete to true
					on error errmessage number errnumber
						--log x & " couldn't update - " & trackpath
						do shell script logcmd & "'" & x & " couldn't update - " & POSIX path of trackpath & "'"
					end try
				end if
				if dodelete then
					try
						do shell script "rm -f '" & POSIX path of trackpath & "'"
						--log x & " deleted - " & trackpath
						do shell script logcmd & "'" & x & " deleted: " & POSIX path of trackpath & "'"
					on error errmessage number errnumber
						--log x & " couldn't delete - " & trackpath
						do shell script logcmd & "'" & x & " couldn't delete: " & POSIX path of trackpath & "'"
					end try
				end if
			end if
			
		end if
	end repeat
end tell

I’ve been meaning to write and use this script for quite a while, but I finally needed to put it together to free up disk space. I hope this helps someone.

  • P. Houston

I should have run that on my whole library before posting it. Here’s my own fix to make it quote lines to “do shell script” the right way:

tell application "iTunes"
	set logcmd to "logger -t iTunesDupFix "
	-- tested quoting with: do shell script logcmd & "does it work or doesn\\'t it: " & quoted form of POSIX path of (location of (file track 1 of library playlist 1) as text)
	
	repeat with x from 1 to count file tracks of library playlist 1
		set thistrack to file track x of library playlist 1
		if location of thistrack is missing value then
			--log "" & x & " missing track - " & name of thistrack as text
			do shell script logcmd & x & " missing track: " & quoted form of (name of thistrack as text)
		else
			
			set trackpath to location of thistrack as text
			
			set oldDelimiters to AppleScript's text item delimiters -- preserve original delimiters
			set AppleScript's text item delimiters to {":"}
			set pathcomponents to text items of trackpath
			set parentpath to (items 1 thru -2 of pathcomponents) as text
			set fullname to last item of pathcomponents
			
			set AppleScript's text item delimiters to {"."}
			set namecomponents to text items of fullname
			set barename to (items 1 thru -2 of namecomponents) as text
			set extension to last item of namecomponents
			set AppleScript's text item delimiters to oldDelimiters -- restore original delimiters
			
			if length of barename > 2 and (character -2 of barename is " " and character -1 of barename is "1") then
				set dupbarename to ((characters 1 thru -3 of barename)) as text
				set dupname to (dupbarename & "." & extension) as text
				set duppath to (parentpath & ":" & dupname) as text
				set doremap to false
				set dodelete to false
				tell application "Finder"
					if exists file trackpath then -- nested if's because this fails: (exists file x) and (exists file y)
						if exists file duppath then
							set tracksize to size of (info for file trackpath)
							set dupsize to size of (info for file duppath)
							if dupsize is equal to tracksize then
								set doremap to true
							else
								--log "" & x & " not duplicate (file size " & dupsize & " vs " & tracksize & ") - " & trackpath
								do shell script logcmd & x & " not duplicate, file size " & dupsize & " vs " & tracksize & ": " & quoted form of POSIX path of trackpath
							end if
						end if
					end if
				end tell
				if doremap then
					try
						set location of thistrack to duppath
						--log "" & x & " updated - "& duppath
						do shell script logcmd & x & " updated: " & quoted form of POSIX path of duppath
						set dodelete to true
					on error errmessage number errnumber
						--log "" & x & " couldn't update - " & duppath
						do shell script logcmd & x & " couldn\\'t update: " & quoted form of POSIX path of duppath
					end try
				end if
				if dodelete then
					try
						do shell script "rm -f " & quoted form of POSIX path of trackpath
						--log "" & x & " deleted - " & trackpath
						do shell script logcmd & x & " deleted: " & quoted form of POSIX path of trackpath
					on error errmessage number errnumber
						--log "" & x & " couldn't delete - " & trackpath
						do shell script logcmd & x & " couldn\\'t delete: " & quoted form of POSIX path of trackpath
					end try
				end if
			end if
			
		end if
	end repeat
end tell

  • P. Houston