Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Perl scripts and MP3

Options
  • 20-07-2007 12:02pm
    #1
    Registered Users Posts: 1,112 ✭✭✭


    Hi All,
    Was thinking of putting this question in the Unix section but think it would be better here.
    Basically in the past I have written Perl code to organise my MP3 collection, or to add new songs to the collection with the same naming conventions
    I've added the code at the end. Maybe someone else will find it useful, or indeed suggest ways to improve it.
    Anyway I have a fairly modest - large MP3 collection and searching for duplicates is a time consuming process. Does anybody have a perl script that will identify duplicates in an MP3 collection.

    What I was thinking was:
    First read in the artist and albums and compare, if a match is found display to user
    Secondly compare song titles (from compilations etc), and again display matches
    Thirdly compare actual file names.

    I would write the script myself, but I am not a great Perl programmer, as anyone who looks at the script below should be able to see so I was hoping someone else would have a similar script that I could re-engineer to suit my needs and then put it back up here.
    Thanks
    Dace
    #!/usr/bin/perl
    
    use MP3::Tag;
    use File::Copy;
    use Getopt::Std;
    
    sub usage()
    {
    	print "\n\n
    	***********************************************************************************
    	This program will scan all sub-directories for mp3 files. Once found a file will be
    	renamed into: 
    	
    	Artist Name - Album - Track Number with leading zero - Track Title.mp3
    	
    	The file will then be moved to a directory structure of:
    	
    	[Destination]\\Artist Name\\Album
    	
    	You can specify the root directory to search, as well as the destination directory
    	as well as whether to copy a file or move it.
    	
    	Errors are written to log file (c:\\rename_log.txt)
    	
    	Extraneous characters are also removed from ID tags
    
    	====================================================================================
    	usage: $0 -[hdtvcs]
    
    	-h		: this (help) message
    	-d		: specify destination. Otherwise c:\Temp is the default.
    	-t		: specify test mode. Files are not moved. Should use -v aswell
    	-v		: verbose output
    	-m		: move files, don't copy
    	-s		: specify source directory.			
    	-r		: scan all subdirectories as well (recursion)
    
    	Example 1: $0 -s c:\\temp -d c:\\music -v -r
    	
    	This will start in c:\\temp and rename all mp3 files in all 
    	subdirectories and move them to c:\\music. It will all write 
    	info to the screen (verbose mode)
    	
    	Example 2 $0 -t
    	
    	This will start in the current directory and scan all mp3 files in the 
    	current directory only (no recursion). Any problems will be logged to 
    	c:\\rename_log.txt, but no files will actually be renamed / moved. 
    	
    	This is useful for seeing what problems exist in the files.
    
    	***********************************************************************************
    	";
    
    	exit;
    }
    
    sub recursive
    {
    
    	foreach $file (<*>)
    	{
    		if (-d $file and $Recurse)
    		{
    			chdir $file;
    			&recursive();
    			chdir "..";
    		}
    		else
    		{
    			if ($file =~ /.mp3$/)
    			{
    				if ($mp3=MP3::Tag->new($file))
    				{
    					#Get Tag Info.
    					@info=$mp3->autoinfo;
    
    					$mp3->new_tag("ID3v1");
    					$mp3->new_tag("ID3v2");
    					#Update tags to remove ` which is used in allofmp3.com instead of '
    					#And it drives me demented.
    					$info[0] =~ s/`/'/g;
    					$info[2] =~ s/`/'/g;
    					$info[3] =~ s/`/'/g;
    
    					#Update tags to remomve stupid punctuation marks
    					$info[0] =~ s/[\/\\?():]//g;
    					$info[2] =~ s/[\/\\?():]//g;
    					$info[3] =~ s/[\/\\?():]//g;
    
    					#Re-write new Tags back to file.
    					$mp3->{ID3v1}->artist($info[2]);
    					$mp3->{ID3v1}->album($info[3]);
    					$mp3->{ID3v1}->song($info[0]);
    					$mp3->{ID3v2}->artist($info[2]);
    					$mp3->{ID3v2}->album($info[3]);
    					$mp3->{ID3v2}->song($info[0]);
    
    					#If there is no track info in the Tag, try get it from filename
    					unless($info[1] =~ m#^(\d+)#)
    					{
    						print "Trying to get track number from filename\n" if $Verbose;
    
    						#Check at the start of the filename
    						unless($file =~ m/^(d+)/g)
    						{
    							open LOG, ">>c:\rename_log.txt";
    							print LOG "\n*******************************\n";
    							print LOG "No Track info found for $file\n";
    							print LOG "Artist\t $info[2]\n";
    							print LOG "Album \t $info[3]\n";
    							print LOG "*******************************\n";
    							close LOG;
    							$errors = 1;
    							next;
    						}
    					}
    
    					if($1 < 10)
    					{
    						$songtitle = "$info[2] - $info[3] - 0$1 - $info[0].mp3";
    					}
    					else
    					{
    						$songtitle = "$info[2] - $info[3] - $1 - $info[0].mp3";
    					}
    					$mp3->{ID3v1}->track($1);
    					$mp3->{ID3v2}->track($1);
    					$mp3->{ID3v1}->write_tag();
    					$mp3->{ID3v2}->write_tag();
    
    					print "new song name will be $songtitle\n" if $Verbose;
    					$mp3->close();
    					# rename ($file, $songtitle) unless $Test;
    
    					unless($Test)
    					{
    						$dest = "$Dest";
    						mkdir $dest;
    
    						$dest = "$Dest\\$info[2]";
    						mkdir $dest;
    
    						$dest = "$Dest\\$info[2]\\$info[3]";
    						mkdir $dest;
    					}
    					#add in new file name
    					$dest = "$dest\\$songtitle";
    					if($Move)
    					{
    						move($file, $dest) unless $Test;
    					}
    					else
    					{
    						print "$dest\n";
    						copy($file, $dest) unless $Test;
    					}
    				}
    			}
    		}
    	}
    }
    
    #Define the options
    my $opt_string = 'hd:tvmrs:';
    
    if(@ARGV == 0)
    {
    	usage();
    }
    
    getopts( "$opt_string", \%opt );
    
    usage() if $opt{h};
    
    #Set destination directory, c:\Temp by default
    $Dest = "c:\\Temp";
    $Dest = $opt{d} if $opt{d};
    
    #Use test mode if -t option is specified.
    $Test = 1 if $opt{t};
    
    #Use verbose mode if -v option is specified.
    $Verbose = 1 if $opt{v};
    
    #Copy files don't move
    $Move = 1 if $opt{m};
    
    #Recursively scan directories
    $Recurse = 1 if $opt{r};
    
    #Set directory to one specified on command line
    chdir($opt{s}) if $opt{s};
    
    #Open current directory and get files.
    &recursive();
    
    [/SIZE]
    


Comments

  • Registered Users Posts: 6,509 ✭✭✭daymobrew


    You could use a hash of hashes that will have the artist/album/track as keys. As you add a MP3 to your library (or find one via dir traversal - File::Find), create an element in the hash. If an element already exists then you have duplicate.


Advertisement