#!/usr/bin/perl ######################################################################################################### # Program: autodelete.pl # # Programmer: George Hadley # # Description: Searches the iTunes xml library file for any song with a rating of 1 star, finds its # # location, and deletes it. Doug Adams's "Super Remove Tracks v.2.1" Applescript is then used # # to clean up the listings in the iTunes GUI (for now). # # Notes: # # 1) URL for "Super Remove Tracks v.2.1" (useful on Mac systems only): # # http://dougscripts.com/itunes/scripts/ss.php?sp=removedeadsuper # # 2) System location for "Super Remove Tracks v.2.1": # # /Users//Library/iTunes/Scripts # # Program History: # # Date Ver Description # # 06/09/2008 0.0 Initial Program created. # # 06/14/2008 1.0 Program successfully parses xml file and gathers song data, log file # # created. Script successfully identifies songs with 1 star ratings. # # Added verbose option for script, executing -i flag with Unix rm. # # 06/19/2008 1.1 Added $entry to count number of deleted entries, made script # # executable. # # 07/11/2008 1.2 Fixed some XML character conversion problems using the URI::Escape # # module. # # 07/13/2008 1.3 Added command line arguments to allow script to work better with a # # crontab. # # To-Do List: # # 1) Provide script with functionality to delete iTunes album artwork associated with deleted tracks # # 2) Enable script to delete listings from iTunes as well as from the physical disk location itself # # 3) Add functionality to delete any artist or album folders emptied as a result of running this # # script # # 4) Reimplement list of hashes as a single hash of arrays or hash of hashes. # # 5) Fix compatibility issues with Windows systems. # # # # License: # # This program is free software; you can redistribute it and/or modify it under the terms of the GNU # # General Public License as published by the Free Software Foundation; either version 2 of the License, # # or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without # # even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General# # Public License for more details. # # # # Get a copy of the GNU General Public License by writing to the Free Software Foundation, Inc., 51 # # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # or visit http://www.gnu.org/copyleft/gpl.html # ######################################################################################################### use strict; use URI::Escape; use Getopt::Long; #Command line argument specifying the location of the iTunes XML file my $xml_file; #Command line argument specifying the location of the script output log file my $log_file; my $verbose = 1; #Command line option used to enable/disable verbose mode GetOptions('xml_file=s'=>\$xml_file, 'log_file=s'=>\$log_file, 'verbose!'=>\$verbose); die "USAGE: autodelete.pl -xml_file -log_file \n" if(!$xml_file||!$log_file); my $id; #Variable containing the current track ID my %rate_hash; #Hash containing rating information for tracks my %loc_hash; #Hash containing location information for tracks my %art_hash; #Hash containing artist information for tracks my %name_hash; #Hash containing title information for tracks my $entry = 0; #Variable to count number of deleted entries print("-I-: XML file: $xml_file\n"); print("-I-: Log file: $log_file\n"); print("-I-: Verbose mode enabled, will ask permission before deleting tracks\n") if($verbose); #open iTunes XML file for reading open(XML,"<",$xml_file)||die("-E-: Unable to open iTunes XML file $xml_file\n"); #open log file to print data to open(LOG,">", $log_file)||die("-E-: Unable to open $log_file for writing!\n"); #search xml file for track info, build info hashes print("-I-: Searching $xml_file for track info.\n"); while() { # find track id if($_ =~ m[(\d+)]) { $id = $1; } elsif($_ =~ m[Rating(\d+)]) { $rate_hash{$id} = $1; } elsif($_ =~ m[Name(.+)]) { $name_hash{$id} = $1; } elsif($_ =~ m[Artist(.+)]) { $art_hash{$id} = $1; } elsif($_ =~ m[Locationfile://localhost(.*)]) { chomp($loc_hash{$id} = $1); $loc_hash{$id} = substr($loc_hash{$id},1) if $^O =~ /Win/; $loc_hash{$id} = uri_unescape($loc_hash{$id}); $loc_hash{$id} =~ s/&/&/g; } if($_ =~ m[Playlists]) { print("-I-: End of tracks found, exiting XML file.\n"); last; } } print("-I-: Deleting 1-star tracks, results written to $log_file\n"); foreach $id (sort keys %rate_hash) { if($rate_hash{$id} == 20) { if($verbose) { print "Remove file $loc_hash{$id}?(y/n):"; unlink("$loc_hash{$id}") or warn("-E-: Unable to delete $loc_hash{$id}: $!\n") if( =~ /\by\b/i) } else { unlink("$loc_hash{$id}") or warn("-E-: Unable to delete $loc_hash{$id}: $!\n"); } if(!-e $loc_hash{$id}) { print LOG ("Track ID: $id\n"); print LOG ("Song: $name_hash{$id}\n"); print LOG ("Artist: $art_hash{$id}\n"); print LOG ("Rating: $rate_hash{$id}\n"); print LOG ("Location: $loc_hash{$id}\n\n"); $entry++; } } } print("-I-: $entry 1-star entries were found, see autodelete.log for details\n");