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"; } }

In reply to Removing Duplicates from Hash of Hash of id3 information by smgfc

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.