1
0
.dotfiles/home/bin/mp3rename

182 lines
3.3 KiB
Perl
Executable File

#!/usr/bin/perl -w
# mp3rename - Rename MP3 files based on their IDv3 tags.
#
# Usage: mp3rename [opts] <mp3s>
#
# 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] <mp3s>
=head1 OPTIONS
--format <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 <directory>
-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");
}