Jenkins
Combining Two iTunes Libraries, No Duplicates Wanted.
I needed to merge my wifes iTunes Library with mine, and decided to write a python script to handle it for me. My main requirement was to not create duplicates, and copy to my library only the music that was exclusive to her library. Basically, copy from hers what I didn’t have. This script should work fine on any two directories with music files. It will simply look for music based on song-title, artist and album info, not by file name or size. This script will not modify either library, but simply creates a third library that contains the difference between the two. No warranty or guarantee implied! I simply stopped coding when this worked for me. I’m simply sharing in case it’s interesting or helpful to someone else. Copy this code, comment on it, or ignore it as you like!
import os
from mutagen.easyid3 import EasyID3
from mutagen.easymp4 import EasyMP4
from mutagen.id3 import ID3NoHeaderError
import traceback
import shutil
def getmlib(rootDir, report = False, log = False):
music_dict = dict()
failures = list()
noid3headers = list()
duplicate_files = list()
for dirName, subdirList, fileList in os.walk(rootDir):
#print('Found directory: %s' % dirName)
for fname in fileList:
spath = dirName + "/" + fname
audio = None
stitle = ''
salbum = ''
sbitrate = 0
slength = 0
sartist = ''
try:
if 'm4a' in fname:
audio = EasyMP4(spath)
else:
audio = EasyID3(spath)
#print '[debug] keys ' + str(audio.valid_keys.keys())
if audio.has_key('title'):
stitle = audio['title'][0]
if audio.has_key('artist'):
sartist = audio['artist'][0]
if audio.has_key('album'):
salbum = audio['album'][0]
skey = stitle + '::' + sartist + '::' + salbum
if music_dict.has_key(skey):
duplicate_files.append(spath)
music_dict[skey] = {'bitrate': sbitrate, 'artist': sartist, 'title': stitle, 'album': salbum, 'file': fname, 'path': dirName}
except ID3NoHeaderError as nm:
noid3headers.append(spath)
except Exception as e:
failures.append({spath: "UNKNOWN FAILURE: \n" + traceback.format_exc()})
if report:
print '[NOID3HEADERS]' + str(len(noid3headers))
print '[UNKNOWN FAILURES]' + str(len(failures))
print '[INFO] Found [%i] songs' % len(music_dict)
print '[INFO] Duplicate count is %i' % len(duplicate_files)
if log:
noidf = open('lib-noid3headers.log', 'w')
for file in noid3headers:
noidf.write(file + '\n')
noidf.close()
dupesf = open('lib-duplicates.log','w')
for file in duplicate_files:
dupesf.write(file + '\n')
dupesf.close()
return music_dict
def getdifflib(core_lib_dir, alt_lib_dir):
core_lib = getmlib(core_lib_dir, report=True, log=True)
alt_lib = getmlib(alt_lib_dir, report=True, log=False)
diff_lib = dict()
for song_key in alt_lib.keys():
if not core_lib.has_key(song_key):
diff_lib[song_key] = alt_lib[song_key]
return diff_lib
def makedifflib(diff_lib, diff_lib_dir):
for song_key in diff_lib:
song = diff_lib[song_key]
artist = song['artist']
album = song['album']
file = song['file']
orig_path = song['path']
new_dir = diff_lib_dir + '/' + artist + '/' + album
if not os.path.exists(new_dir):
os.makedirs(new_dir)
try:
shutil.copy(orig_path + '/' + file, new_dir)
except:
print '[COPY FAIL] trying to copy '
print orig_path
print file
print new_dir
if __name__ == '__main__':
core_lib_dir = '[PATHTO]/Music/iTunes/iTunes Media/Music/'
alt_lib_dir = "[PATHTO]/altmusic/"
diff_lib_dir = "[PATHTO]/diffmusic/"
#core_lib = getmlib(core_lib_dir, report = True, log = True)
diff_lib = getdifflib(alt_lib_dir, core_lib_dir)
makedifflib(diff_lib, diff_lib_dir)
- Combining Two iTunes Libraries, No Duplicates Wanted. Sep 24, 2013 - 3 min read
- Software QA. Jenkins + Jenkins Slave Nodes + Selenium 2 + Browsermob Proxy May 8, 2013 - 3 min read