I’m slowly unwiring the house, replacing all of my Apple Airport Express base stations, mid-range amplifiers, and bookshelf speakers with Sonos wireless speaker systems. The difference in sound is palpable and impressive; I have bass response formerly reserved for live shows in my home office. As with all engineering projects, however, each step forward brings a new set of challenges. First up: combine my three iTunes libraries (on two different Macs and an external drive) into one NAS drive so all Sonos players can see it.
The first and most obvious step is to take the largest of the libraries (on my external drive) and copy it to the NAS drive. Simple enough; took about three hours to get everything onto its new home. Now for the other two libraries, which contain both entirely new bands I’ve discovered since I first moved my iTunes library off-shore and new albums by artists that previously existed in my iTunes library. The problem: iTunes organizes your music by artist, so if you just do a brute-force copy (or drag and drop), you’ll overwrite existing directories (full of lots of music) with the more sparsely populated but newer directories for artists that exist in both places.
While there’s probably some option in MacOS Finder to say “merge directories of the same name, copy those that don’t exist on the target” I found it much easier to create a bash shell script (which I’ve stupidly called “merge.sh”) to do exactly that:
IFS=$(echo -en "\n\b")
for f in $( ls ) ;
if [ -d "$target/$f" ]; then
echo Group $f exists, copying contents
cp -R $source/$f/ $target/$f/
echo Group $f is new, copying directory
cp -R $source/$f $target
Usage is simple:
bash merge.sh "/User/stern/Music/iTunes/iTunes Media/Music" /Volumes/Music
where the first directory is your source (in this case, where iTunes keeps things you’ve imported or downloaded from the store) and the second is the target (where I mounted my NAS drive). It’s important to use quotes around the directory names with spaces in them. The script itself is pretty simple — it generates a list of directory names in the source, and then checks to see if they exist in the target. If so, it uses the trailing-/ and -R options to the Unix
cp tool to do a “contents of directory” copy, effectively merging the two; otherwise it just copies the named directory to the target, creating a new directory. The only other tricky part: Many of your artist and album directories will include spaces in their names, and that makes parsing them into arguments hard. Changing the IFS (input field separator) solves the problem – it removes space as a field separator, so that directory names with embedded spaces are treated as a single argument.