<?xml version="1.0" encoding="windows-1252"?>
<node id="302113" title="rename 0.2 - an improved version of the script which comes with Perl" created="2003-10-25 18:14:56" updated="2005-08-15 04:27:59">
<type id="1748">
sourcecode</type>
<author id="114691">
Aristotle</author>
<data>
<field name="doctext">
&lt;code&gt;
#!/usr/bin/perl
use strict;
use warnings;

=head1 NAME

rename - renames multiple files

=head1 SYNOPSIS

 rename [ -0 ] [ -d ] [ -f ] [ -v ] perlexpr [ files ]
 rename -s [ -0 ] [ -d ] [ -f ] [ -g ] [ -v ] from to [ files ]
 rename -z [ -0 ] [ -d ] [ -f ] [ -v ] [ -z ] [ -z ] [ files ]
 rename -h

=head1 DESCRIPTION

C&lt;rename&gt; renames the filenames supplied according to the rules specified. If a given filename is not modified, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input.

For example, to translate uppercase names to lower, you'd use

 rename 'y/A-Z/a-z/' *

To rename all files matching C&lt;*.bak&gt; to strip the extension, you might say

 rename -s .bak '' *.bak

Although if any of the files has C&lt;.bak&gt; in another part of its filename as well, you'll have to resort to

 rename 's/\.bak$//' *.bak

If you have a directory full of inconveniently named files, you can use C&lt;-z&gt; to clean them up for you.

=head1 ARGUMENTS

=over 4

=item B&lt;-h&gt;, B&lt;--help&gt;

Browse the manpage.

=item I&lt;nothing&gt;

A C&lt;perlexpr&gt; parameter is expected, which should be a Perl expression that assumes the filename in the C&lt;$_&gt; variable and modifies it for the filenames to be renamed.

=item B&lt;-s&gt;, B&lt;--subst&gt;, B&lt;--simple&gt;

Perform a simple textual substitution of C&lt;from&gt; to C&lt;to&gt;. The C&lt;from&gt; and C&lt;to&gt; parameters must immediately follow the argument.

This is equivalent to supplying a C&lt;perlexpr&gt; of C&lt;s/\Qfrom/to/;&gt;.

=item B&lt;-z&gt;, B&lt;--sanitize&gt;

If you specify this option once, (consecutive) blanks in filenames will be replaced by underscores. If you specify it twice, control characters in filenames will also be substituted by underscores. If you specify it thrice, filenames will also be converted to all lowercase.

=back

=head1 OPTIONS

=over 4

=item B&lt;-0&gt;, B&lt;--null&gt;

When reading file names from C&lt;STDIN&gt;, split on null bytes instead of newlines. This is useful in combination with GNU find's C&lt;-print0&gt; option, GNU grep's C&lt;-Z&gt; option, and GNU sort's C&lt;-z&gt; option, to name just a few. B&lt;Only valid if no filenames have been given on the commandline.&gt;

=item B&lt;-d&gt;, B&lt;--dryrun&gt;

Show how the files would be renamed, but don't actually do anything.

=item B&lt;-f&gt;, B&lt;--force&gt;

Rename even when a file with the destination name already exists.

=item B&lt;-g&gt;, B&lt;--global&gt;

In simple mode, substitute all occurences of the string given instead of only the first one. B&lt;Only valid if you specified C&lt;-s&gt;.&gt;

=item B&lt;-v&gt;, B&lt;--verbose&gt;

Print additional information about the operations executed.

=back

=head1 ENVIRONMENT

No environment variables are used.

=head1 AUTHORS

Larry Wall, Robin Barker, Aristotle Pagaltzis

=head1 SEE ALSO

mv(1), perl(1), find(1), grep(1), sort(1)

=head1 DIAGNOSTICS

If you give an invalid Perl expression you'll get a syntax error.

=head1 BUGS

None currently known.

=cut

use Pod::Usage;
use Getopt::Long;

Getopt::Long::Configure('bundling', 'no_ignore_case');
GetOptions(
	'h|help'         =&gt; \my $opt_help,
	's|subst|simple' =&gt; \my $opt_simple,
	'z|sanitize+'    =&gt; \my $opt_sanitize,
	'0|null!'        =&gt; \my $opt_null,
	'f|force!'       =&gt; \my $opt_force,
	'g|global!'      =&gt; \my $opt_global,
	'd|dryrun!'      =&gt; \my $opt_dryrun,
	'v|verbose!'     =&gt; \my $opt_verbose,
) or pod2usage( -verbose =&gt; 1 );

pod2usage( -verbose =&gt; 2 ) if $opt_help;

pod2usage( -verbose =&gt; 1 ) if $opt_global and not $opt_simple;

sub DEBUG { print "@_\n" if $opt_verbose }
sub INFO  { print "@_\n" if $opt_verbose or $opt_dryrun }
sub ERROR { print "@_\n" }

my $code =
	$opt_simple ? do {
		pod2usage( -verbose =&gt; 1 ) if @ARGV &lt; 3;
		my $from = shift @ARGV;
		my $to = shift @ARGV;
		$opt_global
			? sub { s/\Q$from/$to/ }
			: sub { s/\Q$from/$to/g };
	} :
	$opt_sanitize ? sub {
		s/[_[:blank:]]+/_/g;
		s/[_[:cntrl:]]+/_/g if $opt_sanitize &gt; 1;
		s/([[:upper:]]+)/\L$1/g if $opt_sanitize &gt; 2;
	} :
	do {
		my $perlexpr = shift;
		pod2usage( -verbose =&gt; 1 ) if not defined $perlexpr;
		my $evaled = eval "sub { $perlexpr }";
		die $@ if $@;
		$evaled;
	};

pod2usage( -verbose =&gt; 1 ) if $opt_null and @ARGV;

if (!@ARGV) {
	INFO("Reading filenames from STDIN");
	@ARGV = do {
		if($opt_null) {
			INFO("Splitting on null bytes");
			local $/ = "\0";
		}
		&lt;STDIN&gt;;
	};
	chomp @ARGV;
}

for (@ARGV) {
    my $oldname = $_;

    $code-&gt;();

	if($oldname eq $_) {
		DEBUG("'$oldname' unchanged");
		next;
	}

	WARN("'$oldname' not renamed: '$_' already exists"), next
		if not $opt_force and -e;

	if ($opt_dryrun or rename $oldname, $_) {
		INFO("'$oldname' renamed to '$_'");
	}
	else {
		ERROR("Can't rename '$oldname' to '$_': $!");
	}
}

INFO('Dry run, no changes were made.') if $opt_dryrun;
&lt;/code&gt;</field>
<field name="codedescription">
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; obsolete, please check [id://303814] instead.&lt;/p&gt;

&lt;p&gt;You probably know the script that comes with Perl. Initially, I started hacking on it because I didn't want to pull out the old &lt;tt&gt;rename&lt;/tt&gt; binary for very simple substitutions, but found it too cumbersome to write a Perl &lt;tt&gt;s///&lt;/tt&gt; for the same job. Then, feeping creaturism set in and I started adding more and more little stuff.. eventually, it grew to something I wouldn't want to miss from life on the command line.&lt;/p&gt;</field>
<field name="codecategory">
Utility Scripts</field>
<field name="codeauthor">
/msg [Aristotle]</field>
</data>
</node>
