#!/usr/bin/perl -w # #----------------------------------------------------------------------------- # # This is a perl script to check a collection of MP3 files to make sure # they are suitable for burning to an ISO9660 CD-ROM. I need this for # my Aiwa CDC-MP3 disc player. YMMV. --ryan. # # This script uses ID3tool, a command line program that can be found by # pointing your browser at http://www.freshmeat.net/projects/id3tool/ # # This script also uses mp3_check (note the difference), but can manage # without it. http://www.freshmeat.net/projects/mp3_check/ # # If everything is copacetic, this script will return (exit code 0), and # not say a thing. The script will only produce output if there's a problem # (or you used --verbose), and will exit with a non-zero error code. # # This is my first Perl program, and I spent as much time hunched over my # copy of "Programming Perl" as I spent hunched over my keyboard. I make # no promises that any of this is good, correct, or even sane programming # practice. Then again, not much in Perl seems to be good, correct, or sane # programming practice. Oh well. Enjoy. # # Thanks to Andi L6hmus for his suggestions, which made it into version 1.1. #----------------------------------------------------------------------------- # # Copyright (C) 2000 Ryan C. Gordon (icculus@linuxgames.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #----------------------------------------------------------------------------- # Changelog: # 1.0 : First release. # 1.1 : Added ~/.mp3check config file parsing. # Now uses mp3_check (no relation) for verifying mp3 file structure. # Now handles directories and can change their names if needed. # Added --ignore-dir-names option. # Added --ignore-consistency option. # Added --ignore-uppercase option. # Added --ignore-spaces option. # Added --ignore-id3tags option. # Added --ignore-all-files option. # Added --ignore-track-nums option. # Added --no versions of all the options. # Changed my email address. # Corrected spelling of "extension" all over the place. # Improved usage output. # Other tweaks, enhancements, and improvements. #----------------------------------------------------------------------------- # !!! use strict; # !!! FIXME TODO : Read in playlist, if it exists, and attempt to do # !!! FIXME TODO : auto track numbering in a given directory. # globals. $MP3CHECK_VERSION = "1.1"; $examined_files = 0; # Have we actually loooked at a file? $last_album = ""; # Last interactively entered album name. $last_artist = ""; # Last interactively entered artist name. # these are flipped via command lines and the config file. $verbose = 0; # verbose output. $recurse = 0; # descent into directories. $interactive = 0; # Try to clean up stuff? $ignore_playlists = 0; # Don't bitch about playlist existance? $ignore_all_files = 0; # Don't bitch about any non-MP3 file's existance? $ignore_fnsize = 0; # Don't bitch about files/dir > 31 characters. $ignore_id3tags = 0; # Don't examine ID3 tags. $ignore_consistency = 0; # "mp3_check" is installed. $ignore_uppercase = 1; # Don't bitch if filenames have capitals. $ignore_spaces = 0; # Don't bitch if filenames have spaces. $ignore_track_nums = 0; # Don't bitch if track numbers are poorly formed. $ignore_dir_names = 0; # Don't bitch if dir names violate rules. # Don't capitalize these words in track titles. @no_cap = qw(and the of in for on a an to at am are so is as); # subroutines. # usage. woohoo. sub usage { print <<__EOF__; mp3check $MP3CHECK_VERSION Copyright 2001 Ryan C. Gordon This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. There is absolutely no warranty for mp3check. USAGE: $0 [options] file1 file2 ... fileN options: --verbose Chatter a lot during processing. --recurse Descend into subdirectories. --interactive Ask questions, try to fix problems. --ignore-spaces Don't complain if filenames have spaces. --no-ignore-uppercase Don't complain if filenames have capital chars. --ignore-dir-names Don't complain if directores have naming problems. --ignore-fnsize Don't complain if filenames are too long. --ignore-playlists Don't complain if playlists are present. --ignore-all-files Don't complain about ANY non-MP3 files. --ignore-id3tags Don't look at ID3 tag state at all. --ignore-consistency Don't look at MP3 data structure. --ignore-track-nums Don't look at format of track numbers. --help This information. Command line options you use all the time can be added to the file ~/.mp3check, one per line. Also, all these command lines have a "NO" version, so, for example, you can specify --no-ignore-id3tags. This is good for overriding the config file, which overrides the defaults. __EOF__ exit(255); } # check command lines...returns number of NON options. Aborts if there's a # unknown --option. sub check_cmdline { my @toks = @_; my $files_to_check = 0; foreach (@toks) { if (!(/^--/)) { # not an option. $files_to_check++; next; } if ($_ eq "--verbose") { $verbose = 1; print(" * Verbose output requested.\n"); next; } if ($_ eq "--no-verbose") { if ($verbose) { print(" * Verbose output was requested, then disabled.\n"); } $verbose = 0; next; } if ($_ eq "--recurse") { $recurse = 1; next; } if ($_ eq "--no-recurse") { $recurse = 0; next; } if ($_ eq "--interactive") { $interactive = 1; next; } if ($_ eq "--no-interactive") { $interactive = 0; next; } if ($_ eq "--ignore-fnsize") { $ignore_fnsize = 1; next; } if ($_ eq "--no-ignore-fnsize") { $ignore_fnsize = 0; next; } if ($_ eq "--ignore-playlists") { $ignore_playlists = 1; next; } if ($_ eq "--no-ignore-playlists") { $ignore_playlists = 0; next; } if ($_ eq "--ignore-id3tags") { $ignore_id3tags = 1; next; } if ($_ eq "--no-ignore-id3tags") { $ignore_id3tags = 0; next; } if ($_ eq "--ignore-consistency") { $ignore_consistency = 1; next; } if ($_ eq "--no-ignore-consistency") { $ignore_consistency = 0; next; } if ($_ eq "--ignore-uppercase") { $ignore_uppercase = 1; next; } if ($_ eq "--no-ignore-uppercase") { $ignore_uppercase = 0; next; } if ($_ eq "--ignore-spaces") { $ignore_spaces = 1; next; } if ($_ eq "--no-ignore-spaces") { $ignore_spaces = 0; next; } if ($_ eq "--ignore-all-files") { $ignore_all_files = 1; next; } if ($_ eq "--no-ignore-all-files") { $ignore_all_files = 0; next; } if ($_ eq "--ignore-track-nums") { $ignore_track_nums = 1; next; } if ($_ eq "--no-ignore-track-nums") { $ignore_track_nums = 0; next; } if ($_ eq "--ignore-dir-names") { $ignore_dir_names = 1; next; } if ($_ eq "--no-ignore-dir-names") { $ignore_dir_names = 0; next; } if ($_ eq "--help") { usage(); } if ($_ eq "--no-help") { print(" - Fine, I WON'T help you.\n"); # Yes, this is a joke. next; } # other command line checks go here... # if you hit this, you have a bogus command line option. print("Unknown command line option: $_\n"); usage(); } return($files_to_check); } # This tries to find the best way to shrink the filename to 31 or less # chars. First it removes extra dashes, underscores, and whitespace. Then it # tries to remove unneeded chars like apostrophes and parentheses. Then it # tries a hail mary smooshing of all separators: 01-an_mp3 file-with seps.mp3 # becomes 01AnMp3FileWithSeps.mp3. If that STILL doesn't work, we give up, # and truncate the smooshed version to the first 27 chars of the filename # plus the .mp3 extension. sub shrink_file_name { my $mp3file = shift; while ($mp3file =~ s/--/-/) {} # remove double dashes. while ($mp3file =~ s/__/_/) {} # remove double underscores. while ($mp3file =~ s/ / /) {} # remove double spaces. if (length($mp3file) > 31) { # not good enough? while ($mp3file =~ s/\'//) {} # remove apostrophes. while ($mp3file =~ s/\(//) {} # remove parentheses. while ($mp3file =~ s/\)//) {} # remove parentheses. while ($mp3file =~ s/.mp3\Z//i) {} # remove extension briefly. while ($mp3file =~ s/\.//) {} # remove extra periods. $mp3file = $mp3file . ".mp3"; # put extension back on. if (length($mp3file) > 31) { # still not good enough? while ($mp3file =~ s/-/ /) {} # convert dashes to spaces. while ($mp3file =~ s/_/ /) {} # convert underscores to spaces. while ($mp3file =~ s/^ //) {} # trim spaces just in case. while ($mp3file =~ s/ \Z//) {} # trim spaces just in case. while ($mp3file =~ s/ .mp3\Z/.mp3/i) {} # just in case. if (length($mp3file) > 31) { # still not good enough? my $pos = 0; while (($pos = index($mp3file, " ")) > 0) { # convert "my music file name.mp3" to "MyMusicFileName.mp3". $mp3file = substr($mp3file, 0, $pos) . uc(substr($mp3file, $pos + 1, 1)) . substr($mp3file, $pos + 2); } } unless ($ignore_uppercase) { $mp3file =~ tr/[A-Z]/[a-z]/; } # put a dash between track number and title. # Risk truncation, but oh well. If it's that close... if ($mp3file =~ /^\d\d/) { $mp3file = substr($mp3file, 0, 2) . "-" . substr($mp3file, 2); } if (length($mp3file) > 31) { # STILL not good enough? # just truncate. (*shrug*) $mp3file = substr($mp3file, 0, 27) . ".mp3"; } } } print("Enter new file name. [$mp3file] : "); my $new_filename = ; chomp($new_filename); if ($new_filename eq "") { $new_filename = $mp3file; } return($mp3file); } sub change_album_name { if ($ignore_id3tags) { return; } my $mp3file = shift; my $filenameidx = rindex($mp3file, '/') + 1; my $go_ahead = 1; my $new_album = ""; do { $go_ahead = 1; my $x = length($last_album); print("Enter new album name. [$last_album] ($x/30 chars) : "); $new_album = ; chomp($new_album); if ($new_album eq "") { $new_album = $last_album; } if (length($new_album) > 30) { my $trunc = substr($new_album, 0, 30); print(" - [$new_album] is more than 30 characters!\n"); print(" - It will have to be truncated to [$trunc].\n"); unless (getyn("Proceed, with truncation?")) { $go_ahead = 0; } } } until ($go_ahead); if ($new_album ne "") { if (getny("Use [$new_album] for whole directory?")) { $mp3file = "\"" . substr($mp3file, 0, $filenameidx) . "\"*.[mM][pP]3"; } else { $mp3file = "\"$mp3file\""; } $last_album = $new_album; $new_album =~ s/\\\"/\"/g; $new_album =~ s/\"/\\\"/g; `id3tool --set-album=\"$new_album\" $mp3file`; } } sub change_artist_name { if ($ignore_id3tags) { return; } my $mp3file = shift; my $filenameidx = rindex($mp3file, '/') + 1; my $go_ahead = 1; my $new_artist = ""; do { $go_ahead = 1; my $x = length($last_artist); print("Enter new artist name. [$last_artist] ($x/30 chars) : "); $new_artist = ; chomp($new_artist); if ($new_artist eq "") { $new_artist = $last_artist; } if (length($new_artist) > 30) { my $trunc = substr($new_artist, 0, 30); print(" - [$new_artist] is more than 30 characters!\n"); print(" - It will have to be truncated to [$trunc].\n"); unless (getyn("Proceed, with truncation?")) { $go_ahead = 0; } } } until ($go_ahead); if ($new_artist eq "") { $new_artist = $last_artist; } if ($new_artist ne "") { if (getny("Use [$new_artist] for whole directory?")) { $mp3file = "\"" . substr($mp3file, 0, $filenameidx) . "\"*.[mM][pP]3"; } else { $mp3file = "\"$mp3file\""; } $last_artist = $new_artist; $new_artist =~ s/\\\"/\"/g; $new_artist =~ s/\"/\\\"/g; `id3tool --set-artist=\"$new_artist\" $mp3file`; } } sub change_track_number { my $mp3file = shift; my $getout = 0; my $new_track = ""; my $filenameidx = rindex($mp3file, '/') + 1; my $filename = substr($mp3file, $filenameidx); while ($filename =~ s/^\d//) {} # trim off a previous track number. while ($filename =~ s/^_//) {} # trim off a previous separator. while ($filename =~ s/^-//) {} # trim off a previous separator. while ($filename =~ s/^ //) {} # trim off a previous separator. do { print("Enter new track number. [00] : "); $new_track = ; chomp($new_track); if ($new_track eq "") { $new_track = "tooeasytoskipbyandassigntrack00."; } while (length($new_track) < 2) { $new_track = "0" . $new_track; } $getout = 1; for (my $i = 0; (($getout) && ($i < length($new_track))); $i++) { my $ch = substr($new_track, $i, 1); # FIXME: !!! better way to do this? if (($ch lt '0') || ($ch gt '9')) { $getout = 0; } } } while (!$getout); my $newfile = substr($mp3file, 0, $filenameidx) . $new_track . '-'. $filename; if (!rename($mp3file, $newfile)) { print(" - RENAMING FAILED!\n"); $newfile = $mp3file; } return($newfile); } sub getyn { my $promptstr = shift; my $retval = -1; my $answer = ""; while ($retval == -1) { print("$promptstr [Y/n] : "); $answer = lc(); chomp($answer); if (($answer eq "") || ($answer eq "y")) { $retval = 1; } if ($answer eq "n") { $retval = 0; } } return($retval); } sub getny { my $promptstr = shift; my $retval = -1; while ($retval == -1) { print("$promptstr [y/N] : "); my $answer = lc(); chomp($answer); if (($answer eq "") || ($answer eq "n")) { $retval = 0; } if ($answer eq "y") { $retval = 1; } } return($retval); } sub add_mp3_extension { my $mp3file = shift; my $newfile = $mp3file; if (getyn("Append \".mp3\" to file name?")) { $newfile = $newfile . ".mp3"; if (!rename($mp3file, $newfile)) { print(" - RENAMING FAILED!\n"); $newfile = $mp3file; } } return($newfile); } sub change_track_title { if ($ignore_id3tags) { return; } my $mp3file = shift; my $track_guess = $mp3file; my $filenameidx = rindex($mp3file, '/') + 1; $track_guess = lc(substr($track_guess, $filenameidx)); # trim whitespace. while ($track_guess =~ s/^ //) {} while ($track_guess =~ s/ \Z//) {} # lose ".MP3" at end. $track_guess =~ s/.mp3\Z//i; # For tracks such as "01. trackname.mp3"... $track_guess =~ s/^\d\d\.\s//; # lose track numbers, if there. while ($track_guess =~ s/^\d//) {} # turn '_' to spaces. $track_guess =~ s/_/ /g; # turn '-' to spaces. $track_guess =~ s/-/ /g; # Take a gamble on junk like "won_t" and "i_m" and "you_re" and "it_s" ... while ($track_guess =~ s/\sm\b/\'m/i) {} while ($track_guess =~ s/\st\b/\'t/i) {} while ($track_guess =~ s/\sre\b/\'re/i) {} while ($track_guess =~ s/\ss\b/\'s/i) {} # A few others. while ($track_guess =~ s/\shasnt/ hasn't/i) {} while ($track_guess =~ s/\sdont/ don't/i) {} while ($track_guess =~ s/\syoud/ you'd/i) {} # Take a gamble on very simple roman numerals... while ($track_guess =~ s/[iI]i/II/) {} # Try to make acronyms captialize (U.S.A., etc.) while ($track_guess =~ s/[\s\.][a-z]\./uc($&)/e) {} # trim whitespace. while ($track_guess =~ s/^ //) {} while ($track_guess =~ s/ \Z//) {} while ($track_guess =~ s/ / /) {} # FIXME: !!! check for words split by capital letters (smooshing)... # capitalize what we've got. # FIXME: !!! There's got to be a cleaner way to do this. my $pos = index($track_guess, " ") + 1; while ($pos > 0) { my $skip_capitalizing = 0; my $pos2 = index($track_guess, " ", $pos); my $tok = ""; if ($pos2 == -1) { $tok = substr($track_guess, $pos); } else { $tok = substr($track_guess, $pos, $pos2 - $pos); } foreach(@no_cap) { if ($tok eq $_) { $skip_capitalizing = 1; } } if (!$skip_capitalizing) { my $fc = substr($track_guess, $pos, 1); if (($fc eq "(") || ($fc eq "[")) { $pos++; } $track_guess = substr($track_guess, 0, $pos) . uc(substr($track_guess, $pos, 1)) . substr($track_guess, $pos + 1); } $pos = index($track_guess, " ", $pos) + 1; } $track_guess = ucfirst($track_guess); # get first char, too. # !!! FIXME : so much code duplication... my $go_ahead = 1; my $new_title = ""; do { $go_ahead = 1; my $x = length($track_guess); print("Enter new track title. [$track_guess] ($x/30 chars) : "); $new_title = ; chomp($new_title); if ($new_title eq "") { $new_title = $track_guess; } if (length($new_title) > 30) { my $trunc = substr($new_title, 0, 30); print(" - [$new_title] is more than 30 characters!\n"); print(" - It will have to be truncated to [$trunc].\n"); unless (getyn("Proceed, with truncation?")) { $go_ahead = 0; } } } until ($go_ahead); `id3tool --set-title=\"$new_title\" \"$mp3file\"`; } # recurse into a subdir. sub recurse_dir { my $arg1 = shift; if (!opendir(DIRH, $arg1)) { print(" - Couldn't open directory [$arg1]!\n"); return; } if ($verbose) { print(" * Entering directory [$arg1] ...\n"); } my @dirfiles = readdir(DIRH); closedir(DIRH); foreach(@dirfiles) { if (($_ eq ".") || ($_ eq "..")) { next; } check_file("$arg1/$_"); } if ($verbose) { print(" * Leaving directory [$arg1] ...\n"); } } sub get_id3tag_field { my $id3output = shift; my $fieldname = shift; my $retval = ""; my $pos = index($id3output, $fieldname); if ($pos >= 0) { $retval = substr($id3output, $pos + length($fieldname)); $pos = index($retval, "\n"); $retval = substr($retval, 0, $pos - 1); while ($retval =~ s/ \Z//) {} } return($retval); } sub examine_directory { my $dname = shift; my $filenameidx = rindex($dname, '/') + 1; my $filenamesize = (length($dname) - $filenameidx); if (($filenamesize > 31) && (!$ignore_fnsize)) { print(" - [$dname] is (" . $filenamesize . ") chars long, more than 31!\n"); if ($interactive) { # !!! FIXME. print(" - Interactive mode can't fix directory names!\n"); } } if ($recurse) { recurse_dir($dname); } } sub examine_playlist { my $playlistfile = shift; if (!$ignore_playlists) { print(" - [$playlistfile] is probably an unnecessary playlist.\n"); if ( ($interactive) && (getny("Delete file [$playlistfile]?")) ) { if (!unlink($playlistfile)) { print(" - FAILED TO DELETE [$playlistfile]!\n"); } } } } # the actual examination of MP3 files is done here... sub check_file { my $origfile = shift; my $mp3file = $origfile; my $tracknum = ""; my $filenameidx = rindex($mp3file, '/') + 1; my $dir = substr($mp3file, 0, $filenameidx); if ($dir eq "") { $dir = "./"; } my $pos = 0; if ( ($verbose) && (!(-d $mp3file)) ) { print(" * checking [$mp3file] ...\n"); } if (! -e $mp3file) { # doesn't exist? Skip it. print(" - [$mp3file] doesn't exist!\n"); return; } if (-d $mp3file) { # a directory? Check/recurse it. examine_directory($mp3file); } else { if (($mp3file =~ /playlist\Z/i) || ($mp3file =~ /.m3u\Z/i) || ($mp3file =~ /.sfv\Z/i) || ($mp3file =~ /.nfo\Z/i)) { examine_playlist($mp3file); return; } $examined_files = 1; unless ($ignore_track_nums) { if (!(substr($mp3file, $filenameidx) =~ /^\d\d/)) { print(" - [$mp3file] does not start with a two digit number.\n"); if ($interactive) { $mp3file = change_track_number($mp3file); } } # check again, and add to list... # FIXME: !!! Break this duplicate track number checking off into # FIXME: !!! it's own subroutine. # FIXME: !!! This can force you to change an correct track, and leave a # FIXME: !!! misnumbered track with the wrong name. $tracknum = substr($mp3file, $filenameidx, 2); if ($tracknum =~ /^\d\d/) { while (defined $trackhash{$dir}{$tracknum}) { if ($trackhash{$dir}{$tracknum} eq $mp3file) { last; # it's us; it's cool. } print(" - [$mp3file] has the same track number as [$trackhash{$dir}{$tracknum}].\n"); if (!$interactive) { last; # just get out. } else { $mp3file = change_track_number($mp3file); } $tracknum = substr($mp3file, $filenameidx, 2); } } if ($tracknum =~ /^\d\d/) { $trackhash{$dir}{$tracknum} = $mp3file; # add it. } } unless ($ignore_consistency) { my $check = `mp3_check 2>&1 "$mp3file" |grep "BAD_FRAMES "`; chomp($check); $check =~ /BAD_FRAMES (\d*)/; unless ($1 eq "0") { print(" - [$mp3file] has internal corruption! $1 bad frames.\n"); } } unless ($ignore_all_files) { # !!! This should really check if the file is REALLY an mp3, # !!! and then piss and moan if the thing hasn't got an .mp3 # !!! extension. THEN, any other non-playlist files should # !!! prompt for deletion unless $ignore_all_files. if (!($mp3file =~ /.mp3\Z/i)) { print(" - [$mp3file] does not have an .mp3 extension.\n"); if ($interactive) { $mp3file = add_mp3_extension($mp3file); } } } unless ($ignore_id3tags) { my $id3output = `id3tool "$mp3file"`; while ($id3output =~ s/\t//) {} # remove tabs. my $album = get_id3tag_field($id3output, "Album:"); if ($album eq "") { print(" - [$mp3file] has no album in the id3tag!\n"); if ($interactive) { change_album_name($mp3file); } } my $artist = get_id3tag_field($id3output, "Artist:"); if ($artist eq "") { print(" - [$mp3file] has no artist in the id3tag!\n"); if ($interactive) { change_artist_name($mp3file); } } my $title = get_id3tag_field($id3output, "Song Title:"); if ($title eq "") { print(" - [$mp3file] has no track title in the id3tag!\n"); if ($interactive) { change_track_title($mp3file); } } } } my $justname = substr($mp3file, $filenameidx); unless ((-d $mp3file) && ($ignore_dir_names)) { unless ($ignore_spaces) { if ($justname =~ / /) { print(" - [$mp3file] contains spaces!\n"); if ($interactive) { if (getyn("replace with underscores?")) { $justname =~ s/ /_/g; if (!rename($mp3file, $dir . $justname)) { print(" - RENAMING FAILED!\n"); $justname = substr($mp3file, $filenameidx); } else { $mp3file = $dir . $justname; } } } } if ($justname =~ /%20/) { print(" - [$mp3file] contains percent-twenty sequences!\n"); if ($interactive) { if (getyn("replace with underscores?")) { while ($justname =~ s/%20/_/) {} if (!rename($mp3file, $dir . $justname)) { print(" - RENAMING FAILED!\n"); $justname = substr($mp3file, $filenameidx); } else { $mp3file = $dir . $justname; } } } } } unless ($ignore_fnsize) { my $filenamesize = length($justname); while ($filenamesize > 31) { print(" - [$mp3file] is (" . $filenamesize . ") chars long, more than 31!\n"); if ($interactive) { $justname = shrink_file_name($justname); if (!rename($mp3file, $dir . $justname)) { print(" - RENAMING FAILED!\n"); $justname = substr($mp3file, $filenameidx); } else { $mp3file = $dir . $justname; $filenamesize = length($justname); } } else { $filenamesize = 0; # (*shrug*) } } } unless ($ignore_uppercase) { if ($justname =~ /[A-Z]/) { print(" - [$mp3file] has uppercase characters!\n"); if ($interactive) { if (getyn("Convert to lowercase?")) { $justname =~ tr/[A-Z]/[a-z]/; if (!rename($mp3file, $dir . $justname)) { print(" - RENAMING FAILED!\n"); $justname = substr($mp3file, $filenameidx); } else { $mp3file = $dir . $justname; } } } } } } # we may now fail a previously passed test if we changed anything. if ($mp3file ne $origfile) { if ($tracknum =~ /^\d\d/) { delete $trackhash{$dir}{$tracknum}; # don't conflict with ourself. } check_file($mp3file); } } # mainline. if (open(CFGHANDLE, $ENV{HOME} . "/.mp3check")) { my @cfgoptions; while () { chomp; while (s/^ //) {} # trim spaces just in case. while (s/ \Z//) {} # trim spaces just in case. if (!($_ eq "")) { push @cfgoptions, $_; } } close(CFGHANDLE); if (check_cmdline(@cfgoptions) != 0) { print("Non-option specified in ~/.mp3check!\n"); exit(255); } } # actual command lines override config file. if (check_cmdline(@ARGV) == 0) { # no actual files specified? usage(); } # id3tool is pretty important. If it isn't there, and the user hasn't # expressed that ID3 tags don't concern her, then bail. if (($ignore_id3tags == 0) && (`which id3tool 2>&1` =~ /no id3tool in/)) { print(" - id3tool was not found in your PATH. You can get it at:\n"); print(" - http://www.freshmeat.net/projects/id3tool/\n"); print(" - If you don't care about ID3 tags (even though you should),\n"); print(" - then you can run this program without id3tool by using\n"); print(" - the --ignore-id3tags option.\n"); exit 255; } # mp3_check is helpful, but not crucial. if (($ignore_consistency == 0) && (`which mp3_check 2>&1` =~ /no mp3_check in/)) { print(" - mp3_check (a separate tool) was not found in your PATH. You can\n"); print(" - get it at: http://www.freshmeat.net/projects/mp3_check/\n"); print(" - If you don't care about your MP3's internal consistency, or you\n"); print(" - don't want to get mp3_check, then you can disable this warning\n"); print(" - by using the --ignore-consistency option.\n"); } foreach(@ARGV) { if (!($_ =~ /^--/)) { # make sure it's not a command line option... check_file($_); } } if ($examined_files == 0) { print(" - Did not examine any MP3 files!\n"); } exit 0; # end of mp3check.pl ...