[Gllug] Poor scripting?!
John Edwards
john at cornerstonelinux.co.uk
Wed Mar 12 13:09:22 UTC 2008
On Wed, Mar 12, 2008 at 07:51:22AM +0000, Henrik Morsing wrote:
> On Tue, Mar 11, 2008 at 03:36:27PM +0000, John Edwards wrote:
>>
>> Is there any reason you aren't using Perl's own rename program?
>>
>> find . -iname "*pattern*" -print0 | xargs -r0 rename 's/pattern/replacement/g'
>>
>> Of course you may have too many directories for rename to process as
>> arguments. It certain works with several thousand.
> Well, just looked at this and a couple of reasons, one being that I
> don't seem to have that rename program :)
Yes, it doesn't seem to be in the stock Perl tarball but it is
included in the Debian package. Google didn't find the original,
and Debian keeps in a 9000+ line diff file:
http://packages.debian.org/stable/perl
As it's less than a hundred lines of code, I've attached it so you can
use it as a reference. I hope that won't offend others on the mailing
list.
> The other is that with this option I'd have to run find twice (for
> the two different patterns) and running find seems to be what takes
> time.
The GNU version of find can search for multiple patterns with the
-o OR option:
find /dir/ -iname "*pattern1*" -o -iname "*pattern2*"
Then the regex for rename will contain both substitutions:
find /dir/ -iname "*pattern1*" -o -iname "*pattern2*" -print0 | \
xargs -r0 rename 's/pattern1/replace/g ; s/pattern2/replace/g'
> If I run my dedicated Perl script it only needs to run find once
> which takes less than 2 minutes.
The find/xargs method shouldn't take much longer than that for a small
(less than a thousand) number of directories that need to be changed.
> I counted the directories btw and out of 3300 directories it will
> typically change about 60 of them.
Both the find/xargs and pure perl solutions should be able to do that
in a matter of minutes.
Using a dedicated Perl script would allow you include some extra
logging and debugging if you need it. Disadvantage is that like
many Perl scripts it may become hard to maintain over time.
Unless the script is performing a very important function I would go
with whichever is easier for your sysadmins to be comfortable with.
--
#---------------------------------------------------------#
| John Edwards Email: john at cornerstonelinux.co.uk |
| |
| A. Because it breaks the logical sequence of discussion |
| Q. Why is top posting bad ? |
#---------------------------------------------------------#
-------------- next part --------------
#!/usr/bin/perl -w
#
# This script was developed by Robin Barker (Robin.Barker at npl.co.uk),
# from Larry Wall's original script eg/rename from the perl source.
#
# This script is free software; you can redistribute it and/or modify it
# under the same terms as Perl itself.
#
# Larry(?)'s RCS header:
# RCSfile: rename,v Revision: 4.1 Date: 92/08/07 17:20:30
#
# $RCSfile: rename,v $$Revision: 1.5 $$Date: 1998/12/18 16:16:31 $
#
# $Log: rename,v $
# Revision 1.5 1998/12/18 16:16:31 rmb1
# moved to perl/source
# changed man documentation to POD
#
# Revision 1.4 1997/02/27 17:19:26 rmb1
# corrected usage string
#
# Revision 1.3 1997/02/27 16:39:07 rmb1
# added -v
#
# Revision 1.2 1997/02/27 16:15:40 rmb1
# *** empty log message ***
#
# Revision 1.1 1997/02/27 15:48:51 rmb1
# Initial revision
#
use strict;
use Getopt::Long;
Getopt::Long::Configure('bundling');
my ($verbose, $no_act, $force, $op);
die "Usage: rename [-v] [-n] [-f] perlexpr [filenames]\n"
unless GetOptions(
'v|verbose' => \$verbose,
'n|no-act' => \$no_act,
'f|force' => \$force,
) and $op = shift;
$verbose++ if $no_act;
if (!@ARGV) {
print "reading filenames from STDIN\n" if $verbose;
@ARGV = <STDIN>;
chop(@ARGV);
}
for (@ARGV) {
my $was = $_;
eval $op;
die $@ if $@;
next if $was eq $_; # ignore quietly
if (-e $_ and !$force)
{
warn "$was not renamed: $_ already exists\n";
}
elsif ($no_act or rename $was, $_)
{
print "$was renamed as $_\n" if $verbose;
}
else
{
warn "Can't rename $was $_: $!\n";
}
}
__END__
=head1 NAME
rename - renames multiple files
=head1 SYNOPSIS
B<rename> S<[ B<-v> ]> S<[ B<-n> ]> S<[ B<-f> ]> I<perlexpr> S<[ I<files> ]>
=head1 DESCRIPTION
C<rename>
renames the filenames supplied according to the rule specified as the
first argument.
The I<perlexpr>
argument is a Perl expression which is expected to modify the C<$_>
string in Perl for at least some of the filenames specified.
If a given filename is not modified by the expression, it will not be
renamed.
If no filenames are given on the command line, filenames will be read
via standard input.
For example, to rename all files matching C<*.bak> to strip the extension,
you might say
rename 's/\.bak$//' *.bak
To translate uppercase names to lower, you'd use
rename 'y/A-Z/a-z/' *
=head1 OPTIONS
=over 8
=item B<-v>, B<--verbose>
Verbose: print names of files successfully renamed.
=item B<-n>, B<--no-act>
No Action: show what files would have been renamed.
=item B<-f>, B<--force>
Force: overwrite existing files.
=back
=head1 ENVIRONMENT
No environment variables are used.
=head1 AUTHOR
Larry Wall
=head1 SEE ALSO
mv(1), perl(1)
=head1 DIAGNOSTICS
If you give an invalid Perl expression you'll get a syntax error.
=head1 BUGS
The original C<rename> did not check for the existence of target filenames,
so had to be used with care. I hope I've fixed that (Robin Barker).
=cut
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 196 bytes
Desc: Digital signature
URL: <http://mailman.lug.org.uk/pipermail/gllug/attachments/20080312/f1871242/attachment.pgp>
-------------- next part --------------
--
Gllug mailing list - Gllug at gllug.org.uk
http://lists.gllug.org.uk/mailman/listinfo/gllug
More information about the GLLUG
mailing list