#!/usr/bin/perl

#    rename-special-chars.pl - Remove non-US-ASCII and FAT32 reserved
#    characters from the filenames of all files under the current
#    directory.  This makes such files suitable for copying to, for
#    example, an iAudio X5 USB digital audio player.
#
#    Copyright Peter Oliver.
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License,
#    version 2, as published by the Free Software Foundation.
#
#    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.
#    http://www.gnu.org/copyleft/gpl.html
#
#    History:
#    1.0.0, 2005-12-04: Initial release.
#    1.0.1, 2006-06-29: Handle utf8 filesystems.

use warnings;
use strict;
use File::Find;
use Text::Unidecode;
use Encode;
use locale;
use open ':locale';

finddepth( \&callback, '.' );

sub callback {
    return if $_ eq '.';

    # Assume the filename is utf8 if we're using a utf8 locale, and tag
    # the string as such:
    my $decoded = defined( $ENV{'LANG'} ) && $ENV{'LANG'} =~ m/^\w+\.utf8\b/
	? Encode::decode_utf8 $_ 
	: $_;

    my $initial = $decoded;

    # Transliterate to 7 bit ASCII:
    unidecode( $decoded );

    # Remove characters that MS-DOS doesn't like:
    $decoded =~ tr/<>:\"\\|\?\*\//();\'!!.%!/;
    $decoded =~ s/[\. ]+$//;

    # Rename the file if changes have been made:
    if ( $initial ne $decoded ) {
	my $dir = chdir $File::Find::dir;
 	print STDERR "Renaming '$initial' to '$decoded'";
  	rename( $initial, $decoded ) or die ": $!";
	print STDERR "\n";
	chdir $dir;
    }
}
