#!/usr/bin/perl -w use strict; use Getopt::Long; use vars qw ( $debug %spell $spell_re $spell_file @input_files $input_file @input_dirs $input_dir $dir $path ); use subs qw ( init_commandline usage ); sub check_file($); init_commandline; # -- Read file with the spellings -- # File-Format # correct-word=false,false,false... open (FI, $spell_file) or die ("Can't open \"$spell_file\""); while () { chomp; print "Input-Line: $_\n" if ($debug); my ($correct, $false_s) = split (/\s*=\s*/, $_, 2); foreach my $false (split (/\s*,\s*/, $false_s)) { print "Fix: \"$false\" -> \"correct\"\n" if ($debug); $spell{$false} = $correct; } } close (FI); # -- End -- # -- Create the regular expression -- my @temp_spell; foreach my $key (sort {$b cmp $a} keys %spell) { # For keys endig with a "\w"ord-charactar we add a "\b"oundary. # Otherwise we get into trouble with words that begin the same but are longer my $postfix = $key =~ /\w$/ ? '\b' : ''; push @temp_spell, "\Q$key\E$postfix" } $spell_re = join ("\|", @temp_spell); print "Spell_re: $spell_re\n" if ($debug); # -- End -- # Check files, if specified if ($#input_files >= 0) { foreach $input_file (@input_files) { print "Checking file: \"$input_file\"\n" if ($debug); check_file ($input_file); } } # Check dirs, if specified if ($#input_dirs >= 0) { foreach $input_dir (@input_dirs) { print "Checking dir: \"$input_dir\"\n" if ($debug); &traverse($input_dir); } } # When there was no file and/or dir argument(s) then process everything from current dir if ($#input_files == -1 && $#input_dirs -1) { print "No dir/files specifed checking all files in the dir and subdirs\n" if ($debug); &traverse("."); } sub init_commandline { my $helpopt = 0; $debug = 0; $spell_file = "spell-fix.txt"; @input_files = (); @input_dirs = (); my $result = GetOptions( 'help!' => \$helpopt, 'spell-file=s' => \$spell_file, 'file=s' => \@input_files, 'dir=s' => \@input_dirs, 'debug!' => \$debug, ); usage() if $helpopt; } sub usage { print <<"EOF"; Usage: $0 , where valid options are --help # this message :-) --spell-file # File with the correction-list --file # File(s) to be checked --dir # Directory(s) to be checked (recursive!) --debug # Debugging-Messages EOF exit(0); } sub traverse { local($dir) = shift; local($path); unless (opendir(DIR, $dir)) { warn "Can't open $dir\n"; closedir(DIR); return; } foreach (readdir(DIR)) { next if $_ eq '.' || $_ eq '..'; $path = "$dir/$_"; if (-d $path) { # a directory &traverse($path); } elsif (-f _) { # a plain file check_file ($path); } } closedir(DIR); } sub check_file($) { my $file = shift; my $content; open (FI, $file) or return; $content = join ("", ); close (FI); # Correct spelling. Yes this is only a single substitution. :-) if ($content =~ s/\b($spell_re)/$spell{$1}/eg) { print "False spellings found. File: \"$file\"\n" if ($debug); # And write back the file. open (FO, ">$file.tmp") or die ("Can't open file \".tmp$file\" for writing"); print FO $content; close (FO); rename ("$file", "$file.tmp2") or die ("Can't rename \"$file\" -> \"$file.tmp2\""); rename ("$file.tmp", "$file") or die ("Can't rename \"$file.tmp\" -> \"$file\""); unlink ("$file.tmp2") or die ("Can't unlink \"$file.tmp2\""); } else { print "No false spellings found. File: \"$file\"\n" if ($debug); } }