1#!/usr/bin/perl -w 2# $Id: id3tofilename,v 1.7 2003/12/12 06:30:10 ianb Exp $ 3# Ian Beckwith <ianb@nessie.mcc.ac.uk> 4# v1 20030509 5# v2 20031024 MP3::Archive support, more options. 6 7use strict; 8use MP3::Tag; 9use Cwd; 10 11use vars qw($me); 12$me=($0=~/(?:.*\/)?(.*)/)[0]; 13 14my $archive=undef; 15if(eval("require MP3::Archive;")) 16{ 17 $archive=new MP3::Archive; 18} 19else 20{ 21 warn("$me: cannot find MP3::Archive. Carrying on anyway...\n"); 22} 23 24use vars qw($USEEITHER $USEONE $USETWO $ALBUM $TRACK $GUESS); 25$USEEITHER=0; 26$USEONE=1; 27$USETWO=2; 28my $use=$USEEITHER; 29 30$ALBUM=0; 31$TRACK=1; 32$GUESS=2; 33my $tracktype=$GUESS; 34my $verbose=0; 35my $dryrun=0; 36my $doneargs=0; 37my ($dotracknum,$doartist,$doalbum,$dotrack)=(0,0,0,0); 38my $doall=1; 39my $donesomething=0; 40 41while($_=shift) 42{ 43 if(/^-/ && !$doneargs) 44 { 45 if(/-1/) { $use=$USEONE; } 46 elsif(/-2/) { $use=$USETWO; } 47 elsif(/-v/) { $verbose=1; } 48 elsif(/-q/) { $verbose=0; } 49 elsif(/-d/) { $dryrun=1; } 50 elsif(/-a/) { $tracktype=$ALBUM; } 51 elsif(/-t/) { $tracktype=$TRACK; } 52 elsif(/-g/) { $tracktype=$GUESS; } 53 elsif(/-N/) { $dotracknum=1; $doall=0; } 54 elsif(/-A/) { $doartist=1; $doall=0; } 55 elsif(/-L/) { $doalbum=1; $doall=0; } 56 elsif(/-T/) { $dotrack=1; $doall=0; } 57 elsif(/-h/) { usage(); } 58 elsif(/--/) { $doneargs=1; } 59 else { usage(); } 60 next; 61 } 62 $donesomething=1; 63 my $file=$_; 64 unless(-e $file) 65 { 66 warn("$me: $file: not found\n"); 67 next; 68 } 69 70 if($dotracknum && $doartist && $doalbum && $dotrack) 71 { 72 $doall=1; 73 } 74 75 if((!defined($archive)) && (!$doall)) 76 { 77 die("$me: -N, -A, -L and -T only supported with MP3::Archive\n"); 78 } 79 80 my $mp3=MP3::Tag->new($file); 81 unless($mp3) 82 { 83 warn("$me: cannot open $file: $!\n"); 84 next; 85 } 86 87 $mp3->get_tags; 88 89 my $id3=undef; 90 my $ver=undef; 91 if(exists($mp3->{ID3v2})) 92 { 93 unless($use==$USEONE) 94 { 95 $ver="ID3v2"; 96 $id3=$mp3->{ID3v2}; 97 } 98 } 99 elsif(exists($mp3->{ID3v1})) 100 { 101 unless($use==$USETWO) 102 { 103 $ver="ID3v1"; 104 $id3=$mp3->{ID3v1}; 105 } 106 } 107 else 108 { 109 warn("$me: $file: no id3 tags found\n"); 110 next; 111 } 112 113 unless(defined $id3) 114 { 115 warn("$me:$file:cannot find requested ", 116 ("","ID3v1 ","ID3v2 ")[$use], 117 "tag\n"); 118 next; 119 } 120 my $id3tracknum=$id3->track; 121 my $id3artist=$id3->artist; 122 my $id3album=$id3->album; 123 my $id3track=$id3->song; 124 125 $mp3->close; 126 127 unless(defined ($id3tracknum)) 128 { 129 warn("$me:$file:no tracknumber defined in $ver tag\n"); 130 next; 131 } 132 133 unless(defined ($id3artist)) 134 { 135 warn("$me:$file:no artist defined in $ver tag\n"); 136 next; 137 } 138 139 unless(defined ($id3album)) 140 { 141 warn("$me:$file:no album defined in $ver tag\n"); 142 next; 143 } 144 145 unless(defined ($id3track)) 146 { 147 warn("$me:$file:no track defined in $ver tag\n"); 148 next; 149 } 150 151 if($id3tracknum=~/^\d$/) 152 { 153 $id3tracknum="0$id3tracknum"; 154 } 155 156 # default if MP3::Archive not installed 157 my $newfile="$id3tracknum - $id3artist - $id3album - $id3track.mp3"; 158 159 if(defined($archive)) 160 { 161 my ($ftracknum,$fartist,$falbum,$ftrack); 162 if((!$dotracknum) && (!$doall)) 163 { 164 $ftracknum=$archive->tracknum($file,$tracktype); 165 unless(defined($ftracknum)) 166 { 167 print("$me: $file: cannot extract tracknum, skipping.\n"); 168 next; 169 } 170 $id3tracknum=$ftracknum; 171 } 172 if((!$doartist) && (!$doall)) 173 { 174 $fartist=$archive->artist($file,$tracktype); 175 unless(defined($fartist)) 176 { 177 print("$me: $file: cannot extract artist, skipping.\n"); 178 next; 179 } 180 $id3artist=$fartist; 181 } 182 if((!$doalbum) && (!$doall)) 183 { 184 $falbum=$archive->album($file,$tracktype); 185 unless(defined($falbum)) 186 { 187 print("$me: $file: cannot extract album, skipping.\n"); 188 next; 189 } 190 $id3album=$falbum; 191 } 192 if((!$dotrack) && (!$doall)) 193 { 194 $ftrack=$archive->track($file,$tracktype); 195 unless(defined($ftrack)) 196 { 197 print("$me: $file: cannot extract track, skipping.\n"); 198 next; 199 } 200 $id3track=$ftrack; 201 } 202 203 $newfile=$archive->makefilename($file,$id3tracknum,$id3artist,$id3album,$id3track,"mp3",$tracktype); 204 } 205 206 if($newfile eq $file) 207 { 208 next; 209 } 210 211 if(-e $newfile) 212 { 213 warn("$me:$file: cannot rename: file exists: $newfile\n"); 214 next; 215 } 216 217 my $skip=0; 218 unless($dryrun) 219 { 220 unless(rename($file,$newfile)) 221 { 222 $skip=1; 223 warn("$me:$file: cannot rename to $newfile:$!\n"); 224 } 225 } 226 227 if((!$skip) && ($verbose || $dryrun)) 228 { 229 print("$file -> $newfile\n"); 230 } 231} 232 233usage() unless($donesomething); 234 235sub usage 236{ 237 die("Usage: $me [-vqd12atgNALT] file.mp3..\n". 238 " -v\tVerbose.\n". 239 " -q\tQuiet (default).\n". 240 " -d\tDry run (just show what it would do).\n". 241 " -1\tRead ID3v1 tag only.\n". 242 " -2\tRead ID3v2 tag only.\n". 243 " -a\tTreat as album tracks.\n". 244 " -t\tTreat as non-album tracks.\n". 245 " -g\tGuess track type from file location (default).\n". 246 " -N\tSet trackNumber.\n". 247 " -A\tSet Artist.\n". 248 " -L\tSet aLbum.\n". 249 " -T\tSet Track.\n". 250 " -h\tThis help.\n". 251 " --\tEnd of options.\n". 252 "Default: set all four data types.\n". 253 "-N/-A/-L/-T require the current filename to be parsable.\n"); 254} 255 256 257__DATA__ 258 259=head1 NAME 260 261id3tofilename - renames mp3 files based on id3 metadata 262 263=head1 SYNOPSIS 264 265B<id3tofilename> [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<file.mp3>...] 266 267=head1 DESCRIPTION 268 269id3tofilename renames mp3 files based on the metadata in id3 tags. 270For details of how to specify the resulting filename formats, by 271configuring F<.mp3archiverc>, see L<MP3::Archive::Config(3)>. 272 273If any of the B<-N>/B<-A>/B<-L>/B<-T> options are set, it gets the 274remaining data from the current filename, so the filename must already 275be parsable by L<MP3::Archive(3)>. If none of those options are 276supplied, it defaults to setting all data in the filename from the id3 277tags, so the current filename does not have to be in any particular 278format. 279 280=head1 OPTIONS 281 282=over 4 283 284=item B<-v> 285 286Verbose 287 288=item B<-q> 289 290Quiet (no output). This is the default. 291 292=item B<-d> 293 294Dry run. Just show what it would do. 295 296=item B<-1> 297 298Use ID3V1 tag only 299 300=item B<-2> 301 302Use ID3V2 tag only 303 304=item B<-a> 305 306Treat files as album tracks. 307 308=item B<-t> 309 310Treat files as non-album tracks. 311 312=item B<-g> 313 314Guess whether to treat files as album tracks or not, based on the 315current directory of the file. 316 317=item B<-N> 318 319Only set the TRKNUM field from id3 tags. 320 321=item B<-A> 322 323Only set the ARTIST field from id3 tags. 324 325=item B<-L> 326 327Only set the ALBUM field from id3 tags. 328 329=item B<-T> 330 331Only set the TRACK field from id3 tags. 332 333=item B<-h> 334 335Show a short help message. 336 337=back 338 339=head1 BUGS 340 341None known. Please report any found to ianb@nessie.mcc.ac.uk 342 343=head1 SEE ALSO 344 345L<filenametoid3(1)>, L<MP3::Archive(3)>, L<MP3::Archive::Config(3)>, 346L<mp3-archive-tools(1)>, L<mp3lint(1)> 347 348=head1 AUTHOR 349 350Ian Beckwith <ianb@nessie.mcc.ac.uk> 351 352=head1 AVAILABILITY 353 354id3tofilename is part of the mp3-archive-tools package. 355 356The latest version can be found at: 357 358B<http://nessie.mcc.ac.uk/~ianb/projects/mp3-archive-tools/> 359 360=head1 COPYRIGHT 361 362Copyright 2003 Ian Beckwith <ianb@nessie.mcc.ac.uk> 363 364This program is free software; you can redistribute it and/or modify 365it under the terms of the GNU General Public License as published by 366the Free Software Foundation; either version 2 of the License, or (at 367your option) any later version. 368 369This program is distributed in the hope that it will be useful, but 370WITHOUT ANY WARRANTY; without even the implied warranty of 371MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 372General Public License for more details. 373 374You should have received a copy of the GNU General Public License 375along with this program; if not, write to the Free Software 376Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 377 378=cut 379 380 381 382