#!/usr/bin/perl -w # mp3rename - Rename MP3 files based on their IDv3 tags. # # Usage: mp3rename [opts] # # Examples: # mp3rename --format '{artist} - {title}' $HOME/Music/*.mp3 # # This script has POD documentation, so `perldoc mp3rename` # # --Kirsle # http://sh.kirsle.net/ =head1 NAME mp3rename - Rename MP3 files based on their IDv3 tags. =head1 USAGE mp3rename [opts] =head1 OPTIONS --format -f Specify the format to output the files in. Doesn't need to include the .mp3 extension. Example: --format "{artist} - {title}" Format tags include: {artist} - Artist {album} - Album {title} - Song title {track} - Track number Default is: {artist} - {title} --output -o Specify a directory to putput the files to. Default is the current working directory. --recursive -r Recursively descend into any directories included in the arguments. By default, directories will just be skipped over. --copy -c Copy, don't rename. --test -t Show what the files would be renamed to, but don't actually rename them. --help -h -? Show this documentation. =head1 AUTHOR Noah Petherbridge, http://www.kirsle.net/ =cut use strict; use warnings; use File::Basename; use File::Path qw(mkpath); use File::Copy; use Getopt::Long; use MP3::Info; # Get command-line arguments. my %o = ( format => '{artist} - {title}', output => '.', copy => 0, recursive => 0, test => 0, help => 0, ); GetOptions ( 'format|f=s' => \$o{format}, 'output|o=s' => \$o{output}, 'recursive|r' => \$o{recursive}, 'copy|c' => \$o{copy}, 'test|t' => \$o{test}, 'help|h|?' => \$o{help}, ); # Help? &help() if $o{help}; # Get the file list. my @files = @ARGV; if (scalar(@files) == 0) { &help(); } foreach my $file (@files) { if (-d $file && $o{recursive}) { &crawldir($file); } elsif (-d $file) { next; } &rename($file); } sub crawldir { my $dir = shift; opendir (DIR, $dir) or die "Can't crawl into directory $dir: $!"; foreach my $file (sort(grep(!/^\./, readdir(DIR)))) { next if -l "$dir/$file"; # Don't follow links. if (-d "$dir/$file") { &crawldir("$dir/$file"); } elsif (-f "$dir/$file") { &rename("$dir/$file"); } } } sub rename { my $file = shift; return unless -f $file; my $mp3 = get_mp3tag($file); return unless $mp3; my $artist = $mp3->{ARTIST} || "Unknown"; my $album = $mp3->{ALBUM} || "Unknown"; my $title = $mp3->{TITLE} || basename($file, ".mp3"); my $track = $mp3->{TRACKNUM} || ""; # Make the new file name. my $rename = $o{format}; $rename .= ".mp3" unless $rename =~ /\.mp3$/i; $rename =~ s/{artist}/$artist/ig; $rename =~ s/{album}/$album/ig; $rename =~ s/{title}/$title/ig; $rename =~ s/{track}/$track/ig; my $basename = basename($file); # Just testing? if ($o{test}) { print "$basename -> $rename\n"; return; } # Make the output directory? if (!-d $o{output}) { warn "Creating output directory: $o{output}"; mkpath($o{output}) or die "Can't create $o{output}: $!"; } # Rename it. Or copy? if ($o{copy}) { print "COPY: $basename -> $o{output}/$rename\n"; copy($file,"$o{output}/$rename"); } else { print "RENAME: $basename -> $o{output}/$rename\n"; rename($file, "$o{output}/$rename"); } } sub help { exec("perldoc $0"); }