#!/usr/bin/perl # renames files in the current directory the way I (steve) like it # also makes sub directories if the artist has multiple songs # does NOT currently fix up any m3u lists with the new song names # if you use foreign characters in your file names, you need this use locale; use Getopt::Std; use strict; our( $opt_d, $opt_h, $opt_g, $opt_D, $opt_H ); getopts("DdhgH"); usage() if $opt_h; my $dir = "./"; $dir = $ARGV[0] if $ARGV[0]; my $extentions = 'avi|mp\w|mpeg|asf|mov|ogg|rm|ram|wmv'; my $doit = $opt_g; my $debug = $opt_D; my $allow_dirs = $opt_d; my $allow_hidden = $opt_H; # extract the directory that the script lives in my ($progdir) = $0 =~ /^(.+)\//; print "loading hyphenated list..." if $debug; my $hlist = "$progdir/hyphenated.txt"; open HLIST, $hlist or die "cannot open hyphenation list: $hlist: $!"; my @hlist = ; close HLIST; print "done\n" if $debug; print "loading lowercase list..." if $debug; my $lclist = "$progdir/lowercase.txt"; open LCLIST, $lclist or die "cannot open lowercase list: $lclist: $!"; my @lclist = ; close LCLIST; # remove comments @lclist = grep {!/^\#/} @lclist; print "done\n" if $debug; opendir(DIR, "$dir") or die $!; print "opening directory: $dir\n" if $debug; my %makedir; my %newnames; while( my $file = readdir(DIR)){ if( -d $file ){ $makedir{$file}++; } # this should test for existing dirs # ignore "hidden" files if( $file =~ /^\./ && !$allow_hidden ) { next; } print "examining: $file\n" if $debug; # initial filter if( $file =~ /\.($extentions)$/i || ( $allow_dirs && $file !~ /^\.+/ && -d $file )){ print "working on: $file\n" if $debug; my $is_dir = $allow_dirs && -d $file; my $changed = 1; $file = mark_hyphenated( $file ); my $track; my $artist; my $song; my $extension; my $newfile; # first style: [03 -] Artist - songname.mp3 if( $file =~ /^(?:(\b\d{1,2}\b)\s*\-\s*)?([:alpha:][^\-]{1,}|[^\-]{3,})\s*\-\s*(.{2,})(?:\(\d\))?\.($extentions)$/i ){ $track = $1; $artist = $2; $song = $3; $extension = $4; # another style: (artist) songname.mp3 }elsif( $file =~ /^\((.+?)\)\s*(.+)\.($extentions)$/i ){ $artist = $1; $song = $2; $extension = $3; # another style: songname.mp3 }elsif( $file =~ /^(.+)\.($extentions)$/i ){ $song = $1; $extension = $2; $artist = ""; }elsif( $is_dir && $file =~ /^(.+)$/i ){ $song = ""; $artist = $1; $extension = ""; }else{ $changed = 0; print "unknown file pattern. skipping.\n" if $debug; } $file = unmark_hyphenated( $file ); $song = unmark_hyphenated( $song ); $artist = unmark_hyphenated( $artist ); if($changed){ print "processing...\n" if $debug; $artist = fix_escaped( $artist ); $song = fix_escaped( $song ); $artist = pre_regexp( $artist ); $song = pre_regexp( $song ); $artist =~ s/(? $artist, 'song' => $song, 'ext' => $extension, 'track' => $track }; } print "------\n\n" if $debug; } } closedir DIR; #-------------------------------------------------------# # actual files are changed below this point # #-------------------------------------------------------# foreach $dir (keys %makedir){ if($makedir{$dir} > 1 && !-d $dir){ my $command = "mkdir \"$dir\""; if($doit){ print "executing: $command\n"; `$command`; }else{ print "$command\n"; } } } foreach my $file (keys %newnames){ my $newfile; my $command; my %song = %{$newnames{$file}}; my $track = ""; $track = "$song{'track'} - " if $song{'track'}; if($song{'artist'} eq ""){ $newfile = "$track$song{'song'}.$song{'ext'}"; }else{ if($makedir{$song{'artist'}} > 1){ if( $song{'ext'} && $song{'song'} ){ $newfile = "$song{'artist'}/$track$song{'song'}.$song{'ext'}"; }else{ $newfile = "$song{'artist'}"; } }else{ if( $song{'ext'} && $song{'song'} ){ $newfile = "$song{'artist'} - $track$song{'song'}.$song{'ext'}"; }else{ $newfile = "$song{'artist'}"; } } } if($file ne $newfile){ $command = "mv -i \"$file\" \"$newfile\""; if($doit){ print "Renaming $file to $newfile\n"; rename( $file, $newfile ); # `$command`; }else{ print "$command\n"; } } } # gets rid of characters like '!' and the like from a filename sub filterBadChars { # input raw scalar; output scalar with bad chars removed my($name) = @_; $name =~ s/\!|\~|\`//g; return $name; } sub fixCase { # input filename; output case fixed my($file)=@_; $file =~ s/(? USAGE }