- #!/opt/local/bin/perl
- use 5.010;
- use strict;
- use warnings;
- use File::Find qw(find);
- my $library = "F:/Music";
- #$library = "F:/FLAC/Downloaded/New";
- my %files;
- find({ wanted => \&action, no_chdir => 1 }, $library);
- sub action {
- if (-d) {
- my $dn = $File::Find::name;
- %files = getfiles($dn);
- my $fc = keys %files;
- # say $fc;
- unless ($fc == 0) {
- foreach my $fn (sort(keys %files)) {
- rmtag($fn, 'discnumber', 'disctotal', 'rating', 'comment');
- replaygain($fn);
- albumartist($fn, $fc);
- track($fn);
- totaltracks($fn, $fc);
- # empty($fn);
- # duplicate($fn);
- }
- }
- undef %files;
- }
- }
- # Make this subroutine and the whole script so that each file name is stored in a hash and that each member contains an anonymous hash with the tags (the alltags hash).
- # This means it won't have to look up the tags again for the albumartist subroutine.
- sub gettags {
- my $fn = shift;
- my %alltags;
- open(OUTPUT, '-|', qq{metaflac --no-utf8-convert --export-tags-to=- "$fn"}) || die "can\'t run metaflac: $!";
- local $_;
- while (<OUTPUT>) {
- chomp;
- my @tag = split('=');
- my $tagname = lc($tag[0]);
- if ($tag[1]) {
- push @{$alltags{$tagname}}, $tag[1];
- } else {
- push @{$alltags{$tagname}}, 'null';
- }
- }
- close(OUTPUT) || die "couldn\'t close metaflac: $!";
- return %alltags;
- }
- sub getfiles {
- my $dn = shift;
- my %files;
- opendir(my $dh, $dn) or die "Can\'t open directory '$dn': $!";
- foreach (readdir $dh) {
- my $fn = "$dn/$_";
- if (/.flac$/ && -f $fn) {
- $files{$fn} = { gettags($fn) };
- }
- }
- closedir $dh or die "Can\'t close directory '$dn': $!";
- return %files;
- }
- sub replaygain {
- my $fn = shift;
- unless ($files{$fn}{replaygain_reference_loudness}) {
- say "$fn: adding ReplayGain";
- system('metaflac', '--add-replay-gain', $fn);
- }
- }
- sub albumartist {
- my $fn = shift;
- my $tracks = shift;
- if (!$files{$fn}{albumartist}) {
- my $albumartist = 'Various Artists';
- my %artist;
- my $max;
- if ($tracks == 1) {
- $max = $tracks;
- }
- else {
- $max = $tracks / 2;
- }
- foreach my $fn (keys %files) {
- $artist{$files{$fn}{artist}->[0]}++
- }
- if (keys(%artist) <= $max) {
- my $ac = 0;
- foreach my $a (keys %artist) {
- if ($artist{$a} > $ac) {
- $ac = $artist{$a};
- $albumartist = $a;
- }
- }
- }
- say "$fn: adding albumartist tag";
- system('metaflac', "--set-tag=ALBUMARTIST=$albumartist", $fn);
- }
- }
- sub empty {
- my $fn = shift;
- foreach my $k (keys %{$files{$fn}}) {
- foreach (@{$files{$fn}{$k}}) {
- if ($_ eq 'null') {
- say "$fn: WARNING: empty $k tag";
- }
- }
- }
- }
- sub duplicate {
- my $fn = shift;
- my %exists;
- foreach my $k (keys %{$files{$fn}}) {
- foreach (@{$files{$fn}{$k}}) {
- my $tag = quotemeta($k . '=' . $_);
- if ($exists{$tag}) {
- say "$fn: WARNING: duplicate $k tag";
- } else {
- $exists{$tag} = 1;
- }
- }
- }
- }
- sub track {
- my $fn = shift;
- my $track = $files{$fn}{tracknumber}->[0];
- if ($track =~ m/^0/ && $track != 0) {
- say "$fn: fixing tracknumber tag";
- $track =~ s/^0+//;
- system('metaflac', '--remove-tag=TRACKNUMBER', "--set-tag=TRACKNUMBER=$track", $fn);
- }
- }
- sub totaltracks {
- my $fn = shift;
- my $tracks = shift;
- if (
- !$files{$fn}{totaltracks} &&
- !$files{$fn}{tracktotal}
- ) {
- say "$fn: adding totaltracks tag";
- system('metaflac', "--set-tag=TOTALTRACKS=$tracks", $fn);
- }
- elsif (
- $files{$fn}{tracktotal} &&
- !$files{$fn}{totaltracks}
- ) {
- say "$fn: replacing tracktotal tag with totaltracks";
- system('metaflac', '--remove-tag=TRACKTOTAL', "--set-tag=TOTALTRACKS=$files{$fn}{tracktotal}->[0]", $fn);
- }
- }
- sub rmtag {
- my $fn = shift;
- foreach (@_) {
- if ($files{$fn}{$_}) {
- say "$fn: removing $_ tag";
- system('metaflac', "--remove-tag=$_", $fn);
- }
- }
- }
perl flac tag script
Posted by Admin on Thu 17th Mar 2011 15:11
raw | new post
view followups (newest first): perl flac tag script by Admin and perl flac tag script by Admin
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.