#!/usr/bin/perl # # ilp.pl: iTunes library parser # parses exported XML libraries # usage: ilp.pl [-n] OUTPUT # -n skip protected music # output.txt will be sorted by artist then album # use strict; my($dict_counter, $in_tracks, $in_entry, $artist, $album, $is_comp, %data, %artists, $skip_protected, $is_protected); $dict_counter = 0; $in_tracks = 0; $in_entry = 0; $artist = ""; $album = ""; $is_comp = 0; $is_protected = 0; %data = (); %artists = (); $skip_protected = 0; if ($ARGV[0] =~ m#-?-h(elp)?#) { print STDERR "ilp.pl usage:\n"; print STDERR "\t-n|--no-m4p\tskip 'protected' files (purchased music)\n"; exit 0; } elsif($ARGV[0] =~ m#-?-n(o-m4p)?#) { $skip_protected = 1; } while () { if (m##) { $dict_counter++; } elsif (m##) { $dict_counter--; } ## just beginning to parse tracks if (m#Tracks# && $in_tracks == 0 && $dict_counter == 1) { $in_tracks = 1; next; } elsif ($in_tracks == 1 && $dict_counter == 1) { $in_tracks = 0; last; } elsif ($in_entry == 1 && $in_tracks == 1 && $dict_counter == 2) { $in_entry = 0; } elsif ($dict_counter == 3) { $in_entry = 1; } if ($in_entry) { if (m#Artist(.*)#) { $artist = $1; } elsif (m#Album(.*)#) { $album = $1; } elsif (m#Compilation#) { $is_comp = 1; } elsif (m#KindProtected#) { $is_protected = 1; } } elsif (!$in_entry && defined($artist)) { add_data(); next; } } foreach my $k (keys %data) { $artists{"$data{$k}"} ||= []; push(@{$artists{"$data{$k}"}}, $k); } foreach my $k (sort keys %artists) { foreach my $a (sort @{$artists{"$k"}}) { print "$k: $a\n"; } } sub add_data { my($a); if (($is_protected && !$skip_protected) || !$skip_protected) { $album = deHtml($album); $artist = deHtml($artist); ($a=$artist) =~ s#([\#().<>?+*{}])#\\$1#g; if ($is_comp) { $data{"$album"} = "Various Artists"; } else { $data{"$album"} = $artist; } } $album = $artist = undef; $is_protected = $is_comp = 0; } sub deHtml { my($s)=@_; $s =~ s#&\#(\d+);#chr($1)#eg; $s =~ s#>#>#g; $s =~ s#<#<#g; $s =~ s#&#&#g; $s =~ s#"#"#g; return $s; }