Theo has asked for the wisdom of the Perl Monks concerning the following question:

I've been poking at this for some time now, super-searched and checked perlrun, but I'm stuck. I have a dir full of files that I need to rename. The files are similar to these:
newcam_boards.html newcam_boards_contents.html newcam_title.html newcam_title.shtml newcam_title_contents.html newcam_title_contents.shtml
The project got renamed and now I need to change filenames to reflect the change. They should now be:
Ucam_boards.html Ucam_boards_contents.html Ucam_title.html Ucam_title.shtml Ucam_title_contents.html Ucam_title_contents.shtml
The closest I have gotten in my unix system is this one-liner and it's subsequent error:
%perl -e 'while(<*html>){m/newcam(_\w+\.s?html)/;rename $_,Ucam$1}' Can't locate object method "Ucam" via package "_boards.html" at -e lin +e 1.
Am I way off base here?
(PS: Thanks to jeffa and some of his previous post for getting me this far!)

-theo-
(so many nodes and so little time ... )
Note: All opinions are untested, unless otherwise stated

Replies are listed 'Best First'.
Re: batch rename with a 1 liner
by antirice (Priest) on Oct 08, 2003 at 00:27 UTC

    Change it to rename $_,"Ucam$1".

    Hope this helps.

    antirice    
    The first rule of Perl club is - use Perl
    The
    ith rule of Perl club is - follow rule i - 1 for i > 1

Re: batch rename with a 1 liner
by jeffa (Bishop) on Oct 08, 2003 at 03:25 UTC
    You weren't too far off, i prefer to use a for loop instead and avoid explicitly using $1 whenever i can. Here's a little scheme i developed for myself a while back. Start with a simple for loop - grab the files you want and print them out:
    perl -le'for(<*html>){print}'
    Next grab a copy of $_, perform substitution on $_ and print
    perl -le'for(<*html>){$o=$_;s/^new/U/;print}'
    Finally, drop the print and do some damage
    perl -e'for(<*html>){$o=$_;s/^new/U/;rename $o,$_}'
    The first step is just to set up a working one-liner. The second step is important, as you will see what the results will look like, but i still like to live dangerously and just hammer out the third step unless i am using data of any importance. Be safe. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: batch rename with a 1 liner
by vanwie (Acolyte) on Oct 08, 2003 at 00:59 UTC

    Not a perl solution, but...

    If you use bash, you may find the following solution workable:

    $ for i in *.html; do mv $i U${i#new}; done

    See the BASH FAQ (section D3) for more.

      Or cutting out bash-specific stuff:
      for i in *.html; do mv $i `echo $i|sed 's/unwanted/replace/'`; done
      I recommend putting an echo between the do and mv first to make sure it's doing what you expect.

      Will need further work if you have whitespace in filenames.

Re: batch rename with a 1 liner
by greenFox (Vicar) on Oct 08, 2003 at 02:35 UTC
    For a generic solution to this type of problem you can use Larry Wall's rename.pl script from chapter 9 of the Perl Cookbook-
    #!/usr/bin/perl -w # rename - Larry's filename fixer $op = shift or die "Usage: rename expr [files]\n"; chomp(@ARGV = <STDIN>) unless @ARGV; for (@ARGV) { $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; }
    So for your example you would do rename.pl s/^new/U/ *.html *.shtml

    --
    Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho

Re: batch rename with a 1 liner
by idsfa (Vicar) on Oct 08, 2003 at 02:42 UTC

    Golf!

    perl -e 'map{m/new(.*)/;rename $_,"U$1";}<*html>'

    Yes, I know that dot-star is evil.


    Remember, when you stare long into the abyss, you could have been home eating ice cream.
Re: batch rename with a 1 liner
by bart (Canon) on Oct 20, 2003 at 13:20 UTC
    Don't rename a file if the pattern doesn't match!
    m/newcam(_\w+\.s?html)$/ and rename $_, "Ucam$1";