perl rename script

Usage: $ME [OPTION]… PERLEXPR FILE…
Rename FILE(s) using PERLEXPR on each filename.

-b, –backup make backup before removal
-f, –force remove existing destinations, never prompt
-i, –interactive prompt before overwrite
-S, –suffix=SUFFIX override the usual backup suffix
-v, –verbose explain what is being done
-V, –version-control=WORD override the usual version control
-n, –just-print, –dry-run don’t rename, implies –verbose
-l, –link-only link file instead of reame
–help display this help and exit
–version output version information and exit

The backup suffix is ~, unless set with SIMPLE_BACKUP_SUFFIX. The
version control may be set with VERSION_CONTROL, values are:

t, numbered make numbered backups
nil, existing numbered if numbered backups exist, simple otherwise
never, simple always make simple backups

#!/usr/bin/perl

use strict;

use Getopt::Long;
use Text::Abbrev;
use File::Basename;

Getopt::Long::config(qw(bundling));
$Getopt::Long::prefix = '--';

my $ME = $0;
($ME = $0) =~ s!.*/!!;
$| = 1;

my $nothing         = 0;
my $backup          = 0;
my $force           = 0;
my $interactive     = 0;
my $verbose         = 0;
my $help            = 0;
my $version         = 0;
my $linkonly        = 0;
my $backup_suffix   = $ENV{SIMPLE_BACKUP_SUFFIX} || '~';
my $version_control = $ENV{VERSION_CONTROL} || 'existing';

my $vcm             = 0;

sub error {
    my($ERROR) = @_;
    print "$ME: $ERROR\n";
    print "try: `$ME --help' for more information.\n";
    exit 1;
}

{
    local $SIG{__WARN__} = sub {
	if ($_[0] =~ /^Unknown option: (\S+)/) {
	    error("unrecognized option `--$1'");
	} else {
	    print @_;
	}
    };
    GetOptions(
	       'b|backup'             => \$backup,
	       'f|force'              => \$force,
	       'i|interactive'        => \$interactive,
	       'v|verbose'            => \$verbose,
	       'S|suffix=s'           => \$backup_suffix,
	       'V|version-control=s'  => \$version_control,
	       'n|just-print|dry-run' => \$nothing,
               'l|link-only'          => \$linkonly,
	       'help'                 => \$help,
	       'version'              => \$version,
	      );
}

if ($version) {
    print "$ME $VERSION\n";
    exit 0;
}

if ($help) {
    print< VCM_TEST,
	       existing => VCM_TEST,
	       t        => VCM_NUMBERED,
	       numbered => VCM_NUMBERED,
	       never    => 0,
	       simple   => 0,
	   }}{$vcm};
}

my $op = shift
    or error('missing arguments');

if (!@ARGV) {
    @ARGV = ;
    chomp(@ARGV);
}

for (@ARGV) {
    my $was = $_;
    {
        no strict;
        eval $op;
    }
    die $@ if $@;
    next if $was eq $_;

    if (-e $_) {
        unless ($force) {
	    if (! -w && -t) {
		printf "%s: overwrite `%s', overriding mode 0%03o? ",
                       $ME, $_, (stat _)[2]&0777;
		next unless  =~ /^y/i;
	    } elsif ($interactive) {
		print "$ME: replace `$_'? ";
		next unless  =~ /^y/i;
	    }
	}
	if ($backup) {
            my $old;
	    if ($vcm) {
		($old) = sort {($b=~/~(\d*)~/)[0]  ($a=~/~(\d*)~/)[0]} ;
		$old =~ s/~(\d*)~$/'~'.($1+1).'~'/e;
		if ($vcm & VCM_TEST) {
		    $old ||= "$_$backup_suffix";
		} elsif ($vcm & VCM_NUMBERED) {
		    $old ||= "$_.~1~";
		}
	    } else {
		$old = "$_$backup_suffix";
	    }
            print "backup: $_ -> $old\n" if $verbose && $nothing;

            unless ($nothing) {
                if (rename($_,$old)) {
                    warn "$ME: cannot create `$_': $!\n";
                    next;
                }
            }
        }
    }

    print "$was ", $linkonly?"=":'-', "> $_\n" if $verbose || $nothing;

    if (m,/,) {
        my $dir = File::Basename::dirname($_);
        unless (-d $dir) {
            if ($nothing) {
                print "mkdir: $dir\n" if $verbose;
            }
            else {
                mkpath($dir) || next;
            }
         }
    }

    unless ($nothing) {
        if ($linkonly) {
	    link($was,$_) || warn "$ME: cannot create `$_': $!\n";
        } else {
            rename($was,$_) || warn "$ME: cannot create `$_': $!\n";
	}
    }
}

sub mkpath {
    my($path) = @_;
    $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT
    # Logic wants Unix paths, so go with the flow.
    if ($^O eq 'VMS') {
        next if $path eq '/';
        $path = VMS::Filespec::unixify($path);
        if ($path =~ m:^(/[^/]+)/?\z:) {
            $path = $1.'/000000';
        }
    }
    return 1 if -d $path;
    my $parent = File::Basename::dirname($path);
    unless (-d $parent or $path eq $parent) {
        mkpath($parent) || return;
    }
    #print "mkdir: $path\n" if $verbose;
    unless (mkdir($path, 0777)) {
        unless (-d $path) {
            warn "$ME: cannot mkdir `$path': $!\n";
            return;
        }
    }
    return 1;
}

__END__

Advertisements

One thought on “perl rename script

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s