smgfc has asked for the wisdom of the Perl Monks concerning the following question:
Update: This replaces the old scheme of storing mp3s in a hash with theirs paths as keys with a hash of a hash of a hash of a hash, where the keys are, respectively, artist, album, title, and the final values are information on the track (path, size, time, track, and bitrate) as per arunhorne suggestion. The original post is at my scratchpad.
Well, here is my solution to the original problem, so now everything works well. If you have any other suggestions i would love to hear them, even if this is now semi-misplaced (SoPW vs. Code).
The only problem with this code is that you can't include duplicates (id3 wise) anymore even if you want to. I wouldnt be able to do that now, with out concecating a number onto the title key in the big hash of hash of hash of mp3 info, and that is just ugly. If there is another way I would love to hear it.
Another little issue would be sorting the tracks by track number when writing to a file. But i dont have a clue how to do that. Any help is more then welcome
#/usr/bin/perl -w use strict; use Getopt::Std; use MP3::Info; use File::Find; my ($file, @dirs, $tmp, %mp3s, @duplicates, @lines, %options, $artist, + $album, $title); getopts("f:m:rdh", \%options); if ($options{h}) { print <<'eof'; -f file: where to save the mp3 list -m dir: mp3 directory -r: rename the mp3 files according to there id3 tags -d: delete duplicates from the list of mp3s -h: this help document eof exit; } $file = $options{f} || "/Library/Webserver/Documents/mp3.info"; @dirs = $options{m} || ("/Volumes/Storage Drive/Music/"); find(\&id3info, @dirs); sub id3info { return unless $File::Find::name =~ /^.+?\.[Mm][Pp]3$/; $tmp = get_mp3tag($File::Find::name); unless (exists $mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE +'}}) { %{$mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}} = ( 'PATH' => $File::Find::name, 'TRACK' => $$tmp{'TRACK'}, 'TIME' => $$tmp{'TIME'}, 'SIZE' => $$tmp{'SIZE'}, 'BITRATE' => $$tmp{'BITRATE'} ); } else { if ($mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}{'SI +ZE'} < $$tmp{'SIZE'}) { push @duplicates, $mp3s{$artist}{$album}{$title}{'PATH'}; %{$mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}} += ( 'PATH' => $File::Find::name, 'TRACK' => $$tmp{'TRACK'}, 'TIME' => $$tmp{'TIME'}, 'SIZE' => $$tmp{'SIZE'}, 'BITRATE' => $$tmp{'BITRATE'} ); } else { push @duplicates, $File::Find::name; } } } if ($options{d}) { delete_duplicates(\@duplicates); } if ($options{r}) { rename_mp3s(\%mp3s); } foreach $artist (keys %mp3s) { foreach $album (keys %{ $mp3s{$artist} }) { foreach $title (keys %{ $mp3s{$artist}{$album} }) { push @lines, print $artist . '::' . $album . '::' . $title + . '::' . $mp3s{$artist}{$album}{$title}{'PATH'} . "\n"; } } } open (FILE, ">$file") or die ("Can't open $file: $!\n"); foreach (@lines) { print FILE $_; } close (FILE); sub rename_mp3s { my ($mp3s) = @_; my ($artist, $album, $title); foreach $artist (keys %mp3s) { foreach $album (keys %{ $mp3s{$artist} }) { foreach $title (keys %{ $mp3s{$artist}{$album} }) { $mp3s{$artist}{$album}{$title}{'PATH'} =~ /^(.+\/)/; rename $mp3s{$artist}{$album}{$title}{'PATH'}, $1 . $a +rtist . ' - ' . $title . '.mp3'; } } } } sub delete_duplicates { my ($duplicates) = @_; foreach (@$duplicates) { unlink($_) or warn "Couldn't delete $_: $!\n"; } }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Removing Duplicates from Hash of Hash of id3 information
by arunhorne (Pilgrim) on May 27, 2002 at 11:03 UTC | |
|
Re: Removing Duplicates from Hash of Hash of id3 information
by jonknee (Monk) on May 27, 2002 at 13:45 UTC |