#!/usr/bin/perl -w use File::Basename; use Getopt::Std; # check for unicodedecoder my $unidec = 0; eval { require Text::Unidecode; }; unless ($@) { $unidec = 1; Text::Unidecode ->import(); }else{ } # check commandline params my %OPTS; getopts('lea',\%OPTS); # Function prototypes: sub readFiles($); sub renameFile($$); sub help(); ############################################################################## # rename a given File sub renameFile($$){ (my $path,$file) = @_; my $newfile = $file; #remove chars below 32 $newfile =~ s/[\x00-\x1f]/_/g; #urldecode: $newfile =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/chr(hex($1))/ge; #fix broken unicode chars for german umlauts $newfile =~ s/\303\204/Ae/g; $newfile =~ s/\303\226/Oe/g; $newfile =~ s/\303\234/Ue/g; $newfile =~ s/\303\244/ae/g; $newfile =~ s/\303\266/oe/g; $newfile =~ s/\303\274/ue/g; $newfile =~ s/\303\237/ss/g; #convert to latin1 if($unidec){ $newfile = unidecode($newfile); } #add more translations here: $newfile =~ s/\\//g; #remove backspaces $newfile =~ s/\*/x/g; #windows doesn't like this at all :-) $newfile =~ s/&/_and_/g; #ampersand to english $newfile =~ s/@/_at_/g; $newfile =~ s/['"`]//g; #remove these completely #lowercase some known extensions $newfile =~ s/bat$/bat/gi; $newfile =~ s/exe$/exe/gi; $newfile =~ s/ogg$/ogg/gi; $newfile =~ s/mp3$/mp3/gi; $newfile =~ s/rar$/rar/gi; $newfile =~ s/pdf$/pdf/gi; $newfile =~ s/pdb$/pdb/gi; #German Umlauts (Linux charset) $newfile =~ s/ü/ue/g; $newfile =~ s/Ü/Ue/g; $newfile =~ s/ö/oe/g; $newfile =~ s/Ö/Oe/g; $newfile =~ s/ä/ae/g; $newfile =~ s/Ä/Ae/g; $newfile =~ s/ß/ss/g; #German Umlauts (Windows charset) $newfile =~ s/\x8e/Ae/g; $newfile =~ s/\x99/Oe/g; $newfile =~ s/\x9A/Ue/g; $newfile =~ s/\x84/ae/g; $newfile =~ s/\x94/oe/g; $newfile =~ s/\x81/ue/g; $newfile =~ s/\xe1/ss/g; $newfile =~ s/\253/.5/g; #Accents $newfile =~ s/é/e/g; $newfile =~ s/É/E/g; $newfile =~ s/è/e/g; $newfile =~ s/à/a/g; $newfile =~ s/â/a/g; $newfile =~ s/ô/o/g; $newfile =~ s/ñ/n/g; $newfile =~ s/\202/_/g; $newfile =~ s/\212/_/g; $newfile =~ s/_\././g; $newfile =~ s/\.\././g; $newfile =~ s/\357/'/g; #Remove all chars we don't want if($OPTS{'e'}){ $newfile =~ s/[^A-Za-z_0-9\.\-]/_/g; }else{ $newfile =~ s/[^A-Za-z_0-9\(\)\[\]\.\-]/_/g; } #some cleanup $newfile =~ s/_-_/-/g; #Dashes should not be surounded by underscores $newfile =~ s/_-/-/g; $newfile =~ s/-_/-/g; $newfile =~ s/__+/_/g; #Reduce multiple spaces to one #lowercase if wanted $newfile = lc($newfile) if($OPTS{'l'}); if ("$path/$file" ne "$path/$newfile"){ print STDERR "Renaming '$file' to '$newfile'"; if (-e "$path/$newfile"){ print STDERR "\tSKIPPED new file exists\n"; }else{ if (rename("$path/$file","$path/$newfile")){ print STDERR "\tOKAY\n"; }else{ print STDERR "\tFAILED\n"; } } } } ############################################################################## # Read a given directory and its subdirectories sub readFiles($) { (my $path)=@_; opendir(ROOT, $path); my @files = readdir(ROOT); closedir(ROOT); foreach (@files) { next if /^(\.|\.\.)$/; #skip upper dirs next if((/^\./) && (!$OPTS{'a'})); #skip hidden files my $file =$_; my $fullFilename = "$path/$file"; if (-d $fullFilename) { readFiles($fullFilename); #Recursion } renameFile($path,$file); #Rename } } ############################################################################## # prints a short Help text sub help() { print < This tool renames files back to sane names. It does so by replacing spaces, german umlauts and some special chars by underscores. If a renamed version of a file already exists the renaming will be skipped. Options: -l convert to lowercase -e extended cleaning (removes brackets as well) -a convert all files - don't exclude hidden files and dirs The argument can be files and directories. WARNING: Directories will be recurseively changed. _____________________________________________________________________ sanity.pl - Sanitize Filenames Copyright (C) 2003-2005 Andreas Gohr 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. See COPYING for details STOP } ############################################################################## # Main if (@ARGV < 1){ &help(); exit -1; } foreach my $arg (@ARGV){ if(-d $arg){ &readFiles($arg); }else{ &renameFile(dirname($arg),basename($arg)); } }