#!/usr/bin/perl
use warnings;
use strict;
use MP3::Info;
use Getopt::Std;
# some people name files FOO.MP3 and I don't know why
use File::Glob qw/:globally :nocase/;
$Getopt::Std::STANDARD_HELP_VERSION = not undef; # true!
# Quick script to do two things:
# 1) Check for MP3 tags and move ones that don't have them out of the way
# 2) Organize stuff based on artist/album, etc
# This'll do a lot to your filesystem, but it only half-heartedly tries to
# behave.
# pass "-d" if you want to change the dir
our $opt_d;
getopt 'd:';
# editable parameters: just change the strings and all will be well.
# not really constants, but they were hard-coded before.
my $attention = "attention";
my $done = "done";
if ($opt_d) {
chdir $opt_d or die "Couldn't chdir to $opt_d: $!\n"
}
# Set up the $attention and $done directories
for ($attention, $done) {
unless (-e) {
mkdir $_ or die "Couldn't mkdir $_: $!\n"
}
}
# glob is the what the shell does -- handy function
for my $f (glob "*.mp3") {
my $tag = get_mp3tag $f;
# check for MP3 data
unless (defined($tag) && $tag->{TITLE} ne ''
&& $tag->{AUTHOR} ne '' && $tag->{ALBUM} ne '') {
print "No tag info (or only partial info) for file $f!\n";
# move the file unless it's already there
if (-e "$attention/$f") {
warn "??? $attention/$f already exsists!\n"
} else {
rename $f, "$attention/$f" or die "Couldn't move $f: $!\n"
}
}
# get tag data
my $title = $tag->{TITLE};
my $artist = $tag->{ARTIST};
my $album = $tag->{ALBUM};
my $name = "$title - $artist.mp3";
# refuse to move if they exist
if (-e "$done/$artist/$album/$artist - $title.mp3") {
warn "??? $done/$artist/$album/$artist - $title.mp3 already exists!\n"
} else {
my $target = $done;
# make the directories if they don't exist
for ($artist, $album) {
$target .= "/$_";
if (!-e $target) { # some checking & stuff
mkdir $target or die "Couldn't mkdir $target: $!\n"
} elsif (!-d $target) { # sanity check
die "??? $target isn't a directory!\n"
}
}
# finally move the file, i think
if (-e "$target/$name") {
warn "??? $target/$name already exists!\n"
} else {
rename $f, "$target/$name" or die "Couldn't move $f: $!\n"
}
}
}
__END__
## the following is here mostly because cperl-mode is definately not everything
## it is cracked up to be. grrr.
=pod
=head1 NAME
organize.pl - Organizes a large mp3 library into folders
=head1 SYNOPSIS
organize.pl [ B<-d> I<directory> ]
=head1 DESCRIPTION
This script takes either your pwd or the directory you specified on the command
line (just one, folks) and starts organizing your mp3 collection. Requires use
of the L<MP3::Info|MP3::Info> module, available on CPAN.
Any mp3 file that is missing either a) tag info, b) a title, or c) an artist is
moved (not copied) to the directory F<$attention> per specification. All files
with complete data are sent to sub-directories under F<$done>. The
subdirectories are as follows:
=over
=item $done/
=over
=item artist/
=over
=item album/
artist - title.mp3
=back
=back
=back
There's extensive error checking since your filesystem is being mucked around
in. It dies if it can't create directories. If a file is, for whatever
reason, already in place, the script doesn't move the file it's looking at and
prints a warning to STDERR. Useful for shell scripts, grep, etc.
=cut