#!/usr/bin/perl -w # # $Id: rename.pl,v 2.4 2003/01/13 05:28:42 jmates Exp $ # # Copyright (c) 2000-2002, Jeremy Mates. This script is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # Run perldoc(1) on this file for additional documentation. # ###################################################################### # # REQUIREMENTS require 5; use strict; ###################################################################### # # MODULES use Carp; # better error reporting use Getopt::Std; # command line option processing use File::Copy; # if want to copy instead of rename ###################################################################### # # VARIABLES my $VERSION; ($VERSION = '$Revision: 2.4 $ ') =~ s/[^0-9.]//g; my (%opts, $op, $fn); ###################################################################### # # MAIN # parse command-line options getopts('h?cmifvp', \%opts); help() if exists $opts{'h'} or exists $opts{'?'}; # choose which function to use depending on argument; default is to # use the rename() function, but that can be changed to one of copy() # or move() from File::Copy if the name of the script is changed or # appropriate argument is supplied $fn = $opts{'c'} || $0 eq "copy" ? "copy" : "rename"; $fn = $opts{'m'} || $0 eq "move" ? "move" : $fn; # perl expression to run the files by $op = shift; # read from STDIN if no args left chomp(@ARGV = ) unless @ARGV; # and flag the help text if nothing from STDIN help() unless @ARGV; # loop over the files for (@ARGV) { # allow more flexibility in eval statements no strict; $^W = 0; # record what the file was called my $was = $_; # evaluate the expression passed on the command line, # operating on $_ (by default) eval $op; # keel over if something went wrong with the evaluation... die $@ if $@; # skip out early if the filename didn't change next if $was eq $_; # if required, print out what we intend to do print $fn, ' ', $was, ' ', $_, "\n" if $opts{'v'} || $opts{'i'} || $opts{'p'}; # skip out early if we're in the "preview" mode next if $opts{'p'}; # check whether we should drop into interactive mode # when a conflicting file exists if (-e && $opts{'i'} && !$opts{'f'}) { print "$_ exists. Overwrite? (y/[n]) "; next unless =~ /^[Yy]/; } # with error checking, actually attempt the rename or # copy. unless (eval "$fn(\$was, \$_)") { warn "\U$fn\E ERROR $was -> $_ - $!\n"; next; } } exit; ###################################################################### # # SUBROUTINES # a generic help blarb sub help { print <<"HELP"; Usage: $0 [opts] expression [file1 file2 .. fileN] Mangle filenames using perl expressions. Options for version $VERSION: -h/-? Display this message -p preview mode (show changes only) -v be verbose -c copy instead of rename -m move instead of rename or copy -i interactive, prompt if necessary -f force (do not prompt to replace existing files) Run perldoc(1) on this script for additional documentation. HELP exit; } ###################################################################### # # DOCUMENTATION =head1 NAME rename.pl - mangle filenames using perl expressions =head1 SYNOPSIS Append .old to a bunch of files: $ rename.pl 's/$/.old/' * Fix the case on all .C files to lower, doing a preview of changes only: $ rename.pl -p 'tr/A-Z/a-z/' *.C =head1 DESCRIPTION A file renamer that uses user-supplied perl expressions to rename files. Optionally, the copy() or move() routines from File::Copy may be used instead of the builtin rename() function. A preview mode is also available, to allow testing of expressions before any changes are allowed to go to disk. =head1 USAGE $ rename.pl [options] expression [file1 file2 .. fileN] See L<"OPTIONS"> for details on the command line switches supported. If no files are mentioned on the command line, the script will attempt to read them from STDIN, allowing for easy interoperation with various shell utilities. In this case, fix .htm files to .html: $ find . ! -type d -name "*.htm" | rename.pl '$_ .= "l"' =head1 OPTIONS This script currently supports the following command line switches: =over 4 =item B<-h> / B<-?> Prints a brief usage note about the script. =item B<-p> Enable preview mode, no changes will be made to disk. =item B<-v> Be verbose about the whole process. =item B<-c> Copy files instead of renaming them, using copy() from File::Copy. =item B<-m> Move files instead of renaming them. Uses move() from File::Copy, which may not be available in older versions of File::Copy. Since rename() cannot be used across filesystem boundaries, and may not be available on all systems, move() may be a better option in some circumstances. =item B<-i> Interactive mode: prompts for confirmation. =item B<-f> Force mode. Does not prompt to replace existing files. =back =head1 EXAMPLES Remove upper case from a bunch of files: $ rename.pl '$_ = lc' * Dealing with deep directories full of files to be changed can be tricky, especially if the pattern in question is renaming directories, which will throw off the rename of deeper files. The solution is to first change all the directories, then go after the files. For example, to swap out "bad" characters with _ in a deep file tree: $ find . -type d -exec rename.pl 's/[^A-Za-z0-9,.\/_-]/_/g' {} \; $ find . -exec rename.pl 's/[^A-Za-z0-9,.\/_-]/_/g' {} \; =head1 BUGS =head2 Reporting Bugs Newer versions of this script may be available from: http://sial.org/code/perl/ If the bug is in the latest version, send a report to the author. Patches that fix problems or add new features are welcome. =head2 Known Issues Bugs are left as an exercise to the expression writer. :) =head1 SEE ALSO File::Copy, perl(1) =head1 AUTHOR Jeremy Mates, http://sial.org/contact/ =head1 COPYRIGHT Copyright (c) 2000-2002, Jeremy Mates. This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 HISTORY This is a hacked up version of Larry Wall's original rename script distributed with perl under the eg directory, improved by Daniel V. Klien (copy option, interactive mode), and then polished into this form by Jeremy Mates (preview mode, comments in source, move support). =head1 VERSION $Id: rename.pl,v 2.4 2003/01/13 05:28:42 jmates Exp $ =cut