#!/usr/bin/perl
use Getopt::Std;
getopts("dftvx_");
if($#ARGV < 0) {
    (my $progname = $0) =~ s!.*[/\\]!!;
    die <<EOD
usage: $progname [opts] regex files
-d	Exclude directories from the match
-f	Overwrite existing
-t	Test: print substitution results, but don't move anything
-v      Invert: print the files that didn't match. (implies -t)
-x	Exclude file extension from match (ex: /^foo\$/ matches 'foo.bar')
-_	Replace underscores with spaces before running regex

regex is a standard perl substitution: s/// or tr///
EOD
}
$regex = shift;
if($#ARGV < 0) {
    print "nothing to do\n";
    exit;
}

# if you use -d and none of the filenames contains a directoy
# then bad things can happen to filenames that contain '\'.
# but then you didn't need to use -d

if($opt_d) {
    if(grep {m#/#} @ARGV) {
        $dir_sep = '/';
    } else {
        $dir_sep = '\\\\';
    }
}

$files = $moved = $failed = 0;
foreach $file (@ARGV) {
    $files++;
    $_ = $file;
    my $dir = '';
    my $ext = '';
    if($opt_d) {
        s!^(.*$dir_sep)!! and $dir = $1;
    }
    my $time = sprintf "%010d", (stat $file)[9];
    my $timer = sprintf "$time%03d", rand 1000;
    my $old = $_;

    sub md5() {
        open FH, "-|", "md5sum", $file or die "can't exec md5sum: $!\n";
        <FH> =~ /^([0-9a-f]{32}) / or die "can't parse md5sum";
        close FH;
        return $1;
    }

    $ext = $1 if $opt_x and s/(\.[^.\/]*)$//;
    tr/_/ / if $opt__;

    eval $regex;
    next if $@;

    $_ .= $ext;

    if($opt_v) {
        print "$_\n" if $_ eq $old;
        next;
    }
    next if $_ eq $old;
    $moved++;

    print "'$dir$old' => '$dir$_'\n";
    if(!$opt_t and !$opt_f and -e "$dir$_") {
        warn("'$dir$_' exists, skipping.\n");
        $failed++;
        next;
    }
    unless($opt_t) {
        rename("$dir$old", "$dir$_") or warn("mvre '$dir$old' failed\n") and $failed++;
    }
}

printf "\n%d file%s processed, %d %s%s.\n", $files, $files==1 ? "" : "s", $moved-$failed, $opt_t ? "matched" : "moved", $failed ? ", $failed failed" : "";

