utility to sync an itunes playlist to a directory (like a mounted sd card/phone)
at master 89 lines 2.9 kB view raw
1#!/usr/bin/ruby 2# Copyright (c) 2009, 2012, 2013 joshua stein <jcs@jcs.org> 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions 6# are met: 7# 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. The name of the author may not be used to endorse or promote products 14# derived from this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26# 27 28require File.dirname(__FILE__) << "/lib/itunes" 29 30if !ARGV[1] 31 puts "usage: #{$0} <itunes playlist> <destination directory>" 32 exit 33end 34 35playlist = ARGV[0] 36 37if Dir[ARGV[1]].any? 38 destdir = ARGV[1] 39 40 if !destdir.match(/\/$/) 41 destdir += "/" 42 end 43else 44 puts "error: directory \"#{destdir}\" does not exist, exiting" 45 exit 1 46end 47 48puts "querying itunes for playlist \"#{playlist}\"..." 49 50it = ITunes.new 51pl = it.playlist(playlist) 52 53mbytes = pl.total_bytes.to_f / (1024 * 1024) 54 55puts "found #{pl.tracks.length} track#{pl.tracks.length == 1 ? "" : "s"} " << 56 "with size " << sprintf("%0.2fMb", mbytes) 57 58# make sure the destination can hold this playlist 59df_m = `df -m #{destdir}`.split("\n").last.split(" ")[1].to_i 60if mbytes > df_m 61 puts "error: #{destdir} has size of #{df_m}Mb, need #{mbytes.ceil}Mb to sync" 62 exit 1 63end 64 65td = `mktemp -d /tmp/itunes-rsync.XXXXX`.strip 66 67# link each track into the workspace 68print "linking files under #{td}/... " 69pl.tracks.each do |t| 70 tmppath = td + "/" + t.safe_filename_without_gcd 71 72 if !Dir[File.dirname(tmppath)].any? 73 system("mkdir", "-p", File.dirname(tmppath)) 74 end 75 76 File.symlink(t.location, tmppath) 77end 78 79puts "done." 80 81# file times don't ever seem to match up, so only check size 82puts "rsyncing to #{destdir}... " 83system("rsync", "-Lrv", "--size-only", "--progress", "--delete", "#{td}/", 84 destdir) 85 86print "cleaning up... " 87system("rm", "-rf", td) 88 89puts "done."