#!/usr/bin/perl # # "Intelligent" ID3v2 tagger for MP3s # our $VERSION = 0.04; use strict; use warnings; use MP3::Tag; use File::Find::Rule; use File::Spec; use Cwd; my $dir = ""; # Search by default nowhere my $ext = '.mp3'; # Grab files with the extension of .mp3 my $noSplit = 0; # If the file does NOT contain a hyphen, split into artist/title my $titleFirst = 0; # Format: title - artist instead of: artist - title my $artistFromName = 0; # Grab artist from filename my $noOverwrite = 0; # Don't overwrite existing tags my $help = 0; # Show help my $cwd = Cwd::getcwd(); use Getopt::Long; GetOptions("dir=s" => \$dir, "ext=s" => \$ext, "no-split" => \$noSplit, "title-first" => \$titleFirst, "artist-from-name" => \$artistFromName, "no-overwrite" => \$noOverwrite, "help" => \$help); if ($help || !$dir) { print <<" HELP"; $0 - "intelligent" ID3v2 tagger for MP3s, version $VERSION Usage (defaults in brackets): -d, --directory=DIR directory to start search in [$dir] -e, --extension=EXT extension to search for [$ext] --no-split do NOT split the filename into: artist - title [$noSplit] -t, --title-first if not --no-split, use: title - artist instead [$titleFirst] -a, --artist-from-name get the artist from the filename [$artistFromName] --no-overwrite don't overwrite any existing info [$noOverwrite] HELP exit; } my @mp3s = File::Find::Rule->file() ->name("*$ext") ->in($dir); foreach my $mp3 (@mp3s) { my @spec = File::Spec->splitdir(File::Spec->abs2rel($mp3, $dir)); my %file; $file{name} = $spec[$#spec]; if (@spec >= 4) { $file{genre} = $spec[$#spec - 3]; $file{artist} = $spec[$#spec - 2]; $file{album} = $spec[$#spec - 1]; } elsif (@spec == 3) { $file{artist} = $spec[$#spec - 2]; $file{album} = $spec[$#spec - 1]; } elsif (@spec == 2) { $file{artist} = $spec[$#spec - 1]; } my $sansExtension = $file{name}; $sansExtension =~ s/\Q$ext\E\z//; if (!$noSplit && $sansExtension =~ /\s*-\s*/) { my ($artist, $title); unless ($titleFirst) { ($artist, $title) = split /\s*-\s*/, $sansExtension, 2; } else { ($title, $artist) = split /\s*-\s*/, $sansExtension, 2; } $file{title} = $title; $file{artist} = $artist if !$file{artist} || $artistFromName; } else { $file{title} = $sansExtension; } my $tag = MP3::Tag->new($mp3); # read an existing tag $tag->get_tags(); my $id3v2; $id3v2 = exists $tag->{ID3v2} ? $tag->{ID3v2} : $tag->new_tag("ID3v2"); unless ($noOverwrite) { $id3v2->remove_tag; $id3v2 = $tag->new_tag("ID3v2"); $id3v2->add_frame("TIT2", $file{title}) if $file{title}; $id3v2->add_frame("TPE1", $file{artist}) if $file{artist}; $id3v2->add_frame("TALB", $file{album}) if $file{album}; $id3v2->add_frame("TCON", $file{genre}) if $file{genre}; $id3v2->write_tag; } else { $id3v2->remove_frame($_) for qw/TIT2 TPE1 TALB TCON/; $id3v2->add_frame("TIT2", $file{title}) if $file{title}; $id3v2->add_frame("TPE1", $file{artist}) if $file{artist}; $id3v2->add_frame("TALB", $file{album}) if $file{album}; $id3v2->add_frame("TCON", $file{genre}) if $file{genre}; } $id3v2->write_tag; }