#!/usr/bin/perl -w

# pads file names with leading zeros
# first argument is number of leading zeros to pad to
# only really makes sense for numeric file names, but should work on anything

use warnings;
use strict;
use English;
use Getopt::Long;

# vars
my $pad;   # padding (argument, later format string)
my $base;  # file base name
my $ext;   # file extension
my $was;   # old complete file name
my $new;   # new complete file name
# booleans
my $debug; # debugging?
my $noop;  # no-op, do not actually do the rename
my $verbose; # describe operations as they happen

# get options (if any)
die ("command line parse error") if not GetOptions(
	'verbose'	=>	\$verbose,
	'v'		=>	\$verbose,
	'n'		=>	\$noop,
	'd'		=>	\$debug,
	);

# padding determined by first argument
$pad = shift @ARGV;
warn ("pad=$pad") if $debug;
# make sure it's a positive integer
# the first catches non-numeric input, as well as decimals and negatives
# the second catches zero, which the first test allows
die 'padding value is not a positive integer' if ($pad =~ m/[^0-9]/);
die 'padding value is not a positive integer' if ($pad < 1);
# build format string for sprintf use later
# we re-use $pad
$pad = "%0${pad}d";
warn ("pad=$pad") if $debug;

# regexp to capture file base name and extension
# if multiple dots in file name, considers last dot and suffix to be extension
# not using File::Basename because it demands a list of extensions
my $ext_re = qr{
        # capture base name
        (
        .+
        )
        # capture extension
	(
	\.	# single literal dot for file extension
	[^.]+	# one-or-more non-dot characters
	)
	$	# anchor to end of file name
}x;

# loop through each file name argument
for (@ARGV) {
        # save old name from $_ to $was
        $was = $_;
        warn("was=<$was>") if $debug;
        # extract file basename and extension, if any
	if ($was =~ m/$ext_re/) {
	        $base = $1;
		$ext = $2;
		warn "base=<$base>" if $debug;
		warn "ext=<$ext>" if $debug;
	}
	else {
	        # no extension
	        $base = $was; # basename is entire filename
		$ext = ''; # empty string
		warn "no ext" if $debug;
	}
	die 'empty base name' if ($base eq '');
	# construct new file name, basename plus extension
	# if extension is empty, just uses basename
	# we pad the basename with leading zeros as needed
	$new = sprintf($pad,$base) . $ext;
	warn "new=<$new>" if $debug;
	# skip the rename if the names are the same
	next if ($new eq $was);
	# skip the rename if target exists
	if ((-l $new) or (-e $new)) {
		warn("'$was' -> '$new': Target name exists");
		next;
	}
	# handle options
	print "'$was' -> '$new'\n" if $verbose;
	next if $noop; # skip rename if no-op
	# do the rename
	rename ($was, $new) or
		warn("could not rename '$was' to '$new': $!");
}
