#!/usr/bin/perl -w # $Id: id3tofilename,v 1.7 2003/12/12 06:30:10 ianb Exp $ # Ian Beckwith # v1 20030509 # v2 20031024 MP3::Archive support, more options. use strict; use MP3::Tag; use Cwd; use vars qw($me); $me=($0=~/(?:.*\/)?(.*)/)[0]; my $archive=undef; if(eval("require MP3::Archive;")) { $archive=new MP3::Archive; } else { warn("$me: cannot find MP3::Archive. Carrying on anyway...\n"); } use vars qw($USEEITHER $USEONE $USETWO $ALBUM $TRACK $GUESS); $USEEITHER=0; $USEONE=1; $USETWO=2; my $use=$USEEITHER; $ALBUM=0; $TRACK=1; $GUESS=2; my $tracktype=$GUESS; my $verbose=0; my $dryrun=0; my $doneargs=0; my ($dotracknum,$doartist,$doalbum,$dotrack)=(0,0,0,0); my $doall=1; my $donesomething=0; while($_=shift) { if(/^-/ && !$doneargs) { if(/-1/) { $use=$USEONE; } elsif(/-2/) { $use=$USETWO; } elsif(/-v/) { $verbose=1; } elsif(/-q/) { $verbose=0; } elsif(/-d/) { $dryrun=1; } elsif(/-a/) { $tracktype=$ALBUM; } elsif(/-t/) { $tracktype=$TRACK; } elsif(/-g/) { $tracktype=$GUESS; } elsif(/-N/) { $dotracknum=1; $doall=0; } elsif(/-A/) { $doartist=1; $doall=0; } elsif(/-L/) { $doalbum=1; $doall=0; } elsif(/-T/) { $dotrack=1; $doall=0; } elsif(/-h/) { usage(); } elsif(/--/) { $doneargs=1; } else { usage(); } next; } $donesomething=1; my $file=$_; unless(-e $file) { warn("$me: $file: not found\n"); next; } if($dotracknum && $doartist && $doalbum && $dotrack) { $doall=1; } if((!defined($archive)) && (!$doall)) { die("$me: -N, -A, -L and -T only supported with MP3::Archive\n"); } my $mp3=MP3::Tag->new($file); unless($mp3) { warn("$me: cannot open $file: $!\n"); next; } $mp3->get_tags; my $id3=undef; my $ver=undef; if(exists($mp3->{ID3v2})) { unless($use==$USEONE) { $ver="ID3v2"; $id3=$mp3->{ID3v2}; } } elsif(exists($mp3->{ID3v1})) { unless($use==$USETWO) { $ver="ID3v1"; $id3=$mp3->{ID3v1}; } } else { warn("$me: $file: no id3 tags found\n"); next; } unless(defined $id3) { warn("$me:$file:cannot find requested ", ("","ID3v1 ","ID3v2 ")[$use], "tag\n"); next; } my $id3tracknum=$id3->track; my $id3artist=$id3->artist; my $id3album=$id3->album; my $id3track=$id3->song; $mp3->close; unless(defined ($id3tracknum)) { warn("$me:$file:no tracknumber defined in $ver tag\n"); next; } unless(defined ($id3artist)) { warn("$me:$file:no artist defined in $ver tag\n"); next; } unless(defined ($id3album)) { warn("$me:$file:no album defined in $ver tag\n"); next; } unless(defined ($id3track)) { warn("$me:$file:no track defined in $ver tag\n"); next; } if($id3tracknum=~/^\d$/) { $id3tracknum="0$id3tracknum"; } # default if MP3::Archive not installed my $newfile="$id3tracknum - $id3artist - $id3album - $id3track.mp3"; if(defined($archive)) { my ($ftracknum,$fartist,$falbum,$ftrack); if((!$dotracknum) && (!$doall)) { $ftracknum=$archive->tracknum($file,$tracktype); unless(defined($ftracknum)) { print("$me: $file: cannot extract tracknum, skipping.\n"); next; } $id3tracknum=$ftracknum; } if((!$doartist) && (!$doall)) { $fartist=$archive->artist($file,$tracktype); unless(defined($fartist)) { print("$me: $file: cannot extract artist, skipping.\n"); next; } $id3artist=$fartist; } if((!$doalbum) && (!$doall)) { $falbum=$archive->album($file,$tracktype); unless(defined($falbum)) { print("$me: $file: cannot extract album, skipping.\n"); next; } $id3album=$falbum; } if((!$dotrack) && (!$doall)) { $ftrack=$archive->track($file,$tracktype); unless(defined($ftrack)) { print("$me: $file: cannot extract track, skipping.\n"); next; } $id3track=$ftrack; } $newfile=$archive->makefilename($file,$id3tracknum,$id3artist,$id3album,$id3track,"mp3",$tracktype); } if($newfile eq $file) { next; } if(-e $newfile) { warn("$me:$file: cannot rename: file exists: $newfile\n"); next; } my $skip=0; unless($dryrun) { unless(rename($file,$newfile)) { $skip=1; warn("$me:$file: cannot rename to $newfile:$!\n"); } } if((!$skip) && ($verbose || $dryrun)) { print("$file -> $newfile\n"); } } usage() unless($donesomething); sub usage { die("Usage: $me [-vqd12atgNALT] file.mp3..\n". " -v\tVerbose.\n". " -q\tQuiet (default).\n". " -d\tDry run (just show what it would do).\n". " -1\tRead ID3v1 tag only.\n". " -2\tRead ID3v2 tag only.\n". " -a\tTreat as album tracks.\n". " -t\tTreat as non-album tracks.\n". " -g\tGuess track type from file location (default).\n". " -N\tSet trackNumber.\n". " -A\tSet Artist.\n". " -L\tSet aLbum.\n". " -T\tSet Track.\n". " -h\tThis help.\n". " --\tEnd of options.\n". "Default: set all four data types.\n". "-N/-A/-L/-T require the current filename to be parsable.\n"); } __DATA__ =head1 NAME id3tofilename - renames mp3 files based on id3 metadata =head1 SYNOPSIS B [I<-v>] [I<-q>] [I<-d>] [I<-1>] [I<-2>] [I<-a>] [I<-t>] [I<-g>] [I<-N>] [I<-A>] [I<-L>] [I<-T>] [I<-h>] [I...] =head1 DESCRIPTION id3tofilename renames mp3 files based on the metadata in id3 tags. For details of how to specify the resulting filename formats, by configuring F<.mp3archiverc>, see L. If any of the B<-N>/B<-A>/B<-L>/B<-T> options are set, it gets the remaining data from the current filename, so the filename must already be parsable by L. If none of those options are supplied, it defaults to setting all data in the filename from the id3 tags, so the current filename does not have to be in any particular format. =head1 OPTIONS =over 4 =item B<-v> Verbose =item B<-q> Quiet (no output). This is the default. =item B<-d> Dry run. Just show what it would do. =item B<-1> Use ID3V1 tag only =item B<-2> Use ID3V2 tag only =item B<-a> Treat files as album tracks. =item B<-t> Treat files as non-album tracks. =item B<-g> Guess whether to treat files as album tracks or not, based on the current directory of the file. =item B<-N> Only set the TRKNUM field from id3 tags. =item B<-A> Only set the ARTIST field from id3 tags. =item B<-L> Only set the ALBUM field from id3 tags. =item B<-T> Only set the TRACK field from id3 tags. =item B<-h> Show a short help message. =back =head1 BUGS None known. Please report any found to ianb@nessie.mcc.ac.uk =head1 SEE ALSO L, L, L, L, L =head1 AUTHOR Ian Beckwith =head1 AVAILABILITY id3tofilename is part of the mp3-archive-tools package. The latest version can be found at: B =head1 COPYRIGHT Copyright 2003 Ian Beckwith 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =cut