Upload
tombal
View
212
Download
0
Embed Size (px)
Citation preview
8/3/2019 Cleaning Out the Itunes Library
1/14
Cleaning up your iTunes library (on a mac)
After merging two iTunes libraries I was left with many duplicates whichiTunes asked me to delete one by one. I am always looking for efficient
ways to solve boring tasks, so I went off to find a way to solve thisautomatically. Having a mac is great, because it has so many useful andeasy tools to handle those kinds of problems. First of all, there isapplescript, which I never touched before, but it really is the easiest wayto deal with applications on a mac. To give you one example of its greatpowers consider the simple command you can enter in any applescripteditor window
tell application "iTunes" to play
Click "Run" and it plays! Easy, right?
Anyway, I wrote a few applescripts to clean up my library. I couldn't findsimilar scripts or at least not of the kind I wanted them to be (also,deleting duplicates is often available only for cash). I also wanted to learnapplescript. So why not write my own scripts?
I want to share my experiences with other users and I hope they can beuseful for more people out there. I trust on google to spread the word :)
The scripts are (to some extent) optimized to be fast, using some tricks(or flaws) of applescript. Still, deleting the duplicates takes some time,
especially for large libraries. This is however because of iTunes. Deletingis not a simple task for iTunes. It has to update quite a few things in thebackground, so dont be alarmed if you have to wait for some time. Forme, with about 13.000 tracks deleting 6.000 duplicates took about onehour.
All scripts support (at least a simple) logging, i.e. you can check theirprogress by opening a log file, containing stuff like "Handling file xyz,Deleting file uvw". You can use it to check what is happening. You caneasily change it and add more logging messages. You can also turn it off(by writing "false" after the doLogging property). Especially for the script"Clean up your media folder", you might want to try it with a smallerlibrary first, to convince yourself that everything works finely. After all,your music files are valuable and you don't want them to be gone foreveraccidentally! However, my scripts don't really delete files, they just movethem to the trash. So you can always save files, by checking there afterthe whole process.
Finally, here are some of the scripts:
Delete duplicates. This little script finds and deletes duplicates in your
iTunes library (It deletes the library entry, NOT the physical file. Todelete the physical file, look at the "Clean up your music folder"
http://randystraeume.blogspot.com/2011/03/cleaning-up-your-itunes-library-on-mac.htmlhttp://randystraeume.blogspot.com/2011/03/cleaning-up-your-itunes-library-on-mac.html8/3/2019 Cleaning Out the Itunes Library
2/14
script below. This is to avoid deleting files accidentally which youjust added to your iTunes library, without copying to your musicfolder). Two tracks are considered duplicates if they share the sametrack name, artist and album title. Only if those 3 fields are thesame, all of the tracks except one can be deleted. Additionally the
play counts and the grouping entries are "merged" together, i.e. thehighest play count among the duplicates is adopted and anygrouping entry. If you have better suggestions on how to mergetracks, I am open to any suggestions.
Delete dead tracks. This script finds and deletes dead tracks in youriTunes library, i.e. tracks whose path do not point to an existing filein the file system.
Clean up your music folder. This script finds and deletes files in yourmedia folder which are not represented by entries in your iTuneslibrary. I say "files" because you might have copied other files likepictures there and forgot about them or because maybe some othermusic program added hidden index files. If one of the folders in themedia folder is empty, it is deleted as well.m WARNING: You need toadapt the "libPath" to change the location of the media folder. Bydefault it is set to "yourHomeFolder/Music/iTunes/Music". If youdon't, ALL files in the specified folder will be deleted, because noneof the files are present in YOUR iTunes library. You also might wantto change the valid file endings, i.e. the list of file endings, whichare considered to contain media data. ALL other files will be deletedfor sure!!! Anyway, on a mac nothing is deleted immediately. All"deleted" files will be moved to the trash, so you can still save them
if they were deleted incorrectly. Whatever you do, you should firstcheck on a small library if the script does what you want. Don'tblame me later, if all your data are gone!
Any suggestions are welcome. Hope my scripts help you learning applescript or handle your iTunes problem. And here finally the scripts. To runthem, just copy and paste them to a new text edit window, save as"..".scpt. After clicking the apple script editor opens and you can click run.Alternatively you can save the files in the apple script editor asapplication, which then can be run by clicking like a regular app.
1. Delete duplicates
(*This little script finds and deletes duplicates in your iTunes library. Twotracks are considered duplicates if they share the same track name, artistand album title. Only if those 3 fields are the same, all of the tracksexcept one can be deleted. Additionally the play counts and the groupingentries are "merged" together.
You can also use the main handler to delete duplicates in any otherplaylist than the main library.
You can turn on or off logging of deleted tracks. The logging goes to the
8/3/2019 Cleaning Out the Itunes Library
3/14
"logFile.txt" in your home folder.
Any comments [email protected]*)
propertydoLogging : falsepropertytextlog : missing value
onrun {}tellapplication "iTunes" tosetplListtolibrary playlist1main(plList)
endrun
on main(plList)-- set up loggersettextlogtomakeFileLog(((path tohome folder) asstring) &
"logFile.txt")
ifdoLoggingthentextlog's logImportant("Starting deletingduplicates...")
findDuplicates(plList)ifdoLoggingthentextlog's logImportant("Finished deleting
duplicates...")endmain
on findDuplicates(plList)tellapplication "iTunes"
-- find all artistssetartistListtoartistofeverytrackofplListwhoseartistis
notmissing value
setactArtListto {}repeatwithainartistList
ifnot (actArtListcontains (aasstring)) thencopy (aasstring) toendofactArtList
endrepeat
-- find all albums for a given artistrepeatwithainactArtList
setalbListto (albumofeverytrackofplListwhoseartistisaandalbumisnotmissing value)
setactAlbListto {}
repeatwithalinalbListifnot (actAlbListcontains (alasstring)) then
copy (alasstring) toendofactAlbList
endrepeat
8/3/2019 Cleaning Out the Itunes Library
4/14
-- find all tracks with artist a and album alrepeatwithalinactAlbList
settrListto (nameofeverytrackofplListwhoseartistisaandalbumisalandnameisnotmissing value)
setactTrListto {}
repeatwithtrintrListifnot (actTrListcontains (trasstring))
thencopy (trasstring) toendofactTrListendrepeat
-- handle those tracksrepeatwithtrinactTrList
settracksWithThisCombto (everytrackofplListwhoseartistisaandalbumisalandnameistr)
iflengthoftracksWithThisComb > 1 thenmy
mergeTracks(tracksWithThisComb)
repeatwithifrom 2 tolengthoftracksWithThisComb
setttoitemioftracksWithThisComb
ifdoLoggingthen
setstrto (tr & " - " & al &" - " & a)
textlog'slogMessage("Deleting " & str)
endif
deletetendrepeat
endifendrepeat
endrepeat
endrepeatendtell
end findDuplicates
on mergeTracks(possDupl)tellapplication "iTunes"
set mainTrack toitem 1 ofpossDuplset playCount toplayed countofmainTrackset grOfTrack togroupingofmainTrack
setgrto ""set compOfTrack tocompilationofmainTrack
8/3/2019 Cleaning Out the Itunes Library
5/14
setcompto ""
-- collect all information in mainTrackrepeatwithifrom 2 tolengthofpossDupl
settrtoitemiofpossDupl
settrPlCounttoplayed countoftriftrPlCount > playCount thenset playCount to
trPlCount
if(grOfTrackisequal to "") thensettrGrouptogroupingoftrifnot (trGroupisequal to "") thensetgrto
trGroupendif
if(compOfTrackisequal to "") thensettrComptocompilationoftrifnot (trCompisequal to "") thensetcompto
trCompendif
endrepeat
setplayed countofmainTrack to playCountif(grOfTrackisequal to "") thensetgroupingofmainTrack
togr
if(compOfTrackisequal to "") thensetcompilationofmainTracktocomp
endtellend mergeTracks
on makeFileLog(file_path)scriptFileLog
propertyclass : "file log"property_linefeed : characterid 10
-- Writes log messages to a UTF8-encoded text fileon logMessage(the_text)
setftoopen for accessfile_pathwith writepermission
trywrite (the_text & my_linefeed) tofstarting ateof
as class utf8onerror error_message number error_number
close accessferror error_message number error_number
endtryclose accessf
8/3/2019 Cleaning Out the Itunes Library
6/14
end logMessage
on logImportant(the_text)logMessage("****** " & the_text & " ******")
end logImportant
endscriptend makeFileLog
2. Remove dead tracks
(*This script finds and deletes dead tracks in your iTunes library, i.e. trackswhose path does not point to an existing file in the file system.
You can turn on or off logging of deleted tracks. The logging goes to the"logFile.txt" in your home folder.
Any comments [email protected]*)
propertydoLogging : falsepropertytextlog : missing value
onrun {}main()
endrun
onmain()-- set up loggersettextlogtomakeFileLog(((path tohome folder) asstring) &
"logFile.txt")
ifdoLoggingthentextlog's logImportant("Starting deleting dead
tracks...")
tellapplication "iTunes"setlocationstolocationofeverytrackoflibrary playlist1setallTrackstoeverytrackoflibrary playlist1setallNamestonameofeverytrackoflibrary playlist1
repeatwithifrom 1 tolengthoflocationssetloctoitemioflocationsif(locisequal tomissing value) then
setntoitemiofallNamesifdoLoggingthentextlog's logMessage("Deleting
8/3/2019 Cleaning Out the Itunes Library
7/14
dead track " & n)deleteitemiofallTracks
endifendrepeat
endtell
ifdoLoggingthentextlog's logImportant("Finished deleting deadtracks...")endmain
on makeFileLog(file_path)scriptFileLog
propertyclass : "file log"property_linefeed : characterid 10
-- Writes log messages to a UTF8-encoded text fileon logMessage(the_text)
setftoopen for accessfile_pathwith writepermission
trywrite (the_text & my_linefeed) tofstarting ateof
as class utf8onerror error_message number error_number
close accessferror error_message number error_number
endtry
close accessfend logMessage
on logImportant(the_text)logMessage("****** " & the_text & " ******")
end logImportantendscript
end makeFileLog
3. Clean up music folder
(*This script finds and deletes files in your media folder which are notrepresented by entries in your iTunes library. I say "files" because youmight have copied pictures there and forgot or because maybe someother music program added hidden index files. If one of the folders in themedia folder is empty, it is deleted as well.
You can adapt the "libPath" to change the location of the media folder. Bydefault it is set to "yourHomeFolder/Music/iTunes/Music". You also might
8/3/2019 Cleaning Out the Itunes Library
8/14
want to change the valid file endings, i.e. the list of file endings, which areconsidered to contain media data. ALL other files will be deleted forsure!!!Anyway, on a mac nothing is deleted immediately. All "deleted" files willbe moved to the trash, so you can still save them if they were deleted
incorrectly.Whatever you do, you should first see on a small library if the script doeswhat you want. Dont blame me later, if all your data are gone!
You can turn on or off logging. The logging goes to the "logFile.txt" in yourhome folder.
The associative list code is from the excellent book "Learn apple script" byHanaan Rosenthal.
Any comments [email protected]*)
propertydoLogging : falsepropertytextlog : missing valuepropertylibPath : ((path tohome folder) asstring) &"Music:iTunes:Music"propertyvalidFileEndings : {".mp3", ".wav", ".m4p", ".m4a", ".ogg",".avi"}
onrun {}main()
endrun
onmain()-- set up loggersettextlogtomakeFileLog(((path tohome folder) asstring) &
"logFile.txt")
try
cleanupMediaFolder(libPath)onerrorm
textlog's logError(m)endtry
endmain
on cleanupMediaFolder(libPath)ifdoLoggingthentextlog's logMessage("Starting cleaning up media
folder...")
tellapplication "iTunes"-- list all files in the library
8/3/2019 Cleaning Out the Itunes Library
9/14
settrackPathstolocationofeverytrackinlibrary playlist1
-- put them in an associative listset lib tomy make_associative_list()repeatwithtrPathintrackPaths
my addFileToList(trPath, lib)endrepeat
-- check for every file in the media folder if its path iscontained in the list above
set allFilesInMediaFolder tomy listFilesRecursively(libPath)
set AppleScript's text item delimiters to ":"
ifdoLoggingthentextlog's logMessage("Checking files inmedia folder...")
repeatwith fPath in allFilesInMediaFolderifdoLoggingthentextlog's logMessage("Handling " &
fPath)
-- check if every single path element can be found in libsetpathItemstotext itemsoffPathsetfoundtotrue
setcurLsttolib
repeatwithifrom 1 to (lengthofpathItems)set pathItem toitem i ofpathItems
if(iisequal to (lengthofpathItems)) thenifnot (curLstcontains (pathItem)) then
setfoundtofalseendif
elseset lst4pathItem to getItem(pathItem) of
curLstif(lst4pathItemisequal tomissing value)
thensetfoundtofalseexitrepeat
endifset curLst to lst4pathItem
endifendrepeat
-- every file which is not contained, can be deletedifnotfoundthen
ifdoLoggingthentextlog's logMessage("Deleting" & fPath)
8/3/2019 Cleaning Out the Itunes Library
10/14
tellapplication "Finder" todeletefilefPathendif
endrepeat
ifdoLoggingthentextlog's logMessage("Finished checking
files in media folder.")
set AppleScript's text item delimiters to {""}
-- delete empty foldersmy deleteFoldersRecursively(libPath)
endtell
ifdoLoggingthentextlog's logMessage("Finished cleaning upmedia folder...")end cleanupMediaFolder
on deleteFoldersRecursively(pathToFolder)setfileListto {}tellapplication "System Events"
-- handle filessetfilesListtopathofeveryfileinfolderpathToFolder
repeatwithpathOfFinfilesListset foundValidFileEnding tofalserepeatwith fileEnding in validFileEndings
if(pathOfFends withfileEnding) thenset foundValidFileEnding totrueexitrepeat
endifendrepeatiffoundValidFileEnding thencopy pathOfF toendof
fileListendrepeat
-- handle folderssetfoldersListtopathofeveryfolderinfolderpathToFolder
repeatwithpathOfFinfoldersListset fileList to fileList & my
deleteFoldersRecursively(pathOfF)endrepeat
iffileListisequal to {} thenifdoLoggingthentextlog's logMessage("Deleting folder
" & pathToFolder)deletefolderpathToFolder
endifreturnfileList
8/3/2019 Cleaning Out the Itunes Library
11/14
endtellend deleteFoldersRecursively
on listFilesRecursively(pathToFolder)setfileListto {}
tellapplication "System Events"-- handle filessetfilesListtopathofeveryfileinfolderpathToFolder
repeatwithpathOfFinfilesListset foundValidFileEnding tofalserepeatwith fileEnding in validFileEndings
if(pathOfFends withfileEnding) thenset foundValidFileEnding totrueexitrepeat
endifendrepeatiffoundValidFileEnding thencopy pathOfF toendof
fileListendrepeat
-- handle folderssetfoldersListtopathofeveryfolderinfolderpathToFolder
repeatwithpathOfFinfoldersListset fileList to fileList & my listFilesRecursively(pathOfF)
endrepeatreturnfileList
endtellend listFilesRecursively
on addFileToList(f, lst)setfPathto (fasstring)
set AppleScript's text item delimiters to ":"set pathItems totext itemsoffPath
set AppleScript's text item delimiters to {""}
setcurLsttolstrepeatwithifrom 1 to ((lengthofpathItems) - 1)
set pathItem toitem i ofpathItemsset lst4pathItem to getItem(pathItem) ofcurLstif(lst4pathItemisequal tomissing value) then
if(iisequal to ((lengthofpathItems) - 1)) thensetlst4pathItemto {}
else
set lst4pathItem to make_associative_list()endif
8/3/2019 Cleaning Out the Itunes Library
12/14
curLst's setItem(pathItem, lst4pathItem)endifset curLst to lst4pathItem
endrepeat
copy (lastitemofpathItems) toendofcurLstend addFileToList
on makeFileLog(file_path)scriptFileLog
propertyclass : "file log"property_linefeed : characterid 10
-- Writes log messages to a UTF8-encoded text fileon logMessage(the_text)
setftoopen for accessfile_pathwith writepermission
trywrite (the_text & my_linefeed) tofstarting ateof
as class utf8onerror error_message number error_number
close accessferror error_message number error_number
endtryclose accessf
end logMessage
on logImportant(the_text)logMessage("****** " & the_text & " ******")
end logImportant
on logError(the_text)logMessage("ERROR: " & the_text)
end logErrorendscript
end makeFileLog
on make_associative_list()script AssociativeList
propertyclass : "associative list"propertythe_items : {}propertytheKeys : {}propertytheKeysRef: a referencetotheKeys
ongetKeys()settheKeysto {}considering diacriticals, hyphens, punctuation and
white space butignoring caserepeatwithrecord_refinmythe_items
8/3/2019 Cleaning Out the Itunes Library
13/14
set keyOfRec tokeyofrecord_refcopykeyOfRectoendoftheKeysRef
endrepeatendconsideringreturntheKeys
end getKeys
on find_record_for_key(the_key)(* This is a private handler. Users should not use it
directly. *)considering diacriticals, hyphens, punctuation and
white space butignoring caserepeatwithrecord_refinmythe_items
ifkeyofrecord_ref= the_keythenreturnrecord_ref
endrepeatendconsideringreturnmissing value
end find_record_for_key
on setItem(the_key, the_value)set record_refto find_record_for_key(the_key)ifrecord_ref= missing valuethen
setendofmy the_items to {key:the_key,value:the_value}
else
set the_value ofrecord_refto the_valueendifreturn
end setItem
on getItem(the_key)set record_refto find_record_for_key(the_key)ifrecord_ref= missing valuethen
--error "The key wasn't found." number -1728 fromthe_key
returnmissing value
endifreturn value ofrecord_ref
end getItem
on count_items()returncountmythe_items
end count_items
on delete_item(the_key)set record_refto find_record_for_key(the_key)
ifrecord_refismissing valuethenerror "The key wasn't found." number -1728 from
8/3/2019 Cleaning Out the Itunes Library
14/14
the_keyendifsetcontentsofrecord_reftomissing valuesetmythe_itemstoeveryrecordofmythe_itemsreturn
end delete_itemendscript
end make_associative_list