Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

My pattern for "in-place edit" for many files

by merlyn (Sage)
on Sep 28, 2001 at 20:30 UTC ( #115428=note: print w/replies, xml ) Need Help??

in reply to One-shot code critique

My pattern for "search and replace many files" is to first grab the filenames, usually with File::Find, and then use "inplace editing mode" to do the reading and writing while I concentrate on the editing part.
use File::Find; { my @starters = @ARGV ? @ARGV : qw(/home/merlyn); @ARGV = (); find sub { push @ARGV, $File::Find::name if /\.asp$/; # or whatever condition + here }, @starters; } { local $/; # slurp it local $^I = ".bak"; while (<>) { # $_ now contains the entire file, alter at will s/foo/bar/g; print; } }

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
Re: My pattern for "in-place edit" for many files
by C-Keen (Monk) on Sep 29, 2001 at 13:56 UTC
    This question is a little bit offtopic maybe, but this is puzzling me since I have seen it in a couple of other nodes too. Why are you using two different code blocks in this example? Has it something to do with the lexical scope of the variables?

    Thank You very much! Regards,

      I've found that limiting the scope of my temporaries has reduced my debugging time. So when I need a "scratch variable" for a few steps, or need to set something dangerously global like $/ for a few steps, I pop open a block and do the work there.

      Doing so makes it very clear to the reader that this variable doesn't need a long lifetime, and even ensures that the action won't collide with a larger-scoped variable. It's a slick trick, and works nicely.

      I've also recently started using the idiom of a one-iteration foreach loop to "name" a value rather than setting up a temporary, like:

      for ($some->complicated(@value)->{$to_fetch}) { print; # print it print LOGFILE $_; # and to the logfile substr($_, 0, 1, ""); # remove its first character }
      It's a nice idiom, and is also the explanation of why Larry intentially allows foreach to be spelled "f-o-r". And the "backwards foreach" makes it even easier:
      do_this($_), do_that($_, @moreargs) for $some{$complicated}{$value};

      -- Randal L. Schwartz, Perl hacker

        Doesn't the for-loop construct use more internal resources than a local variable? As comming from the C programming section a waste of resources looks somehow awkwardly to me. But it sure is more readable this way.


Re: My pattern for "in-place edit" for many files
by tphyahoo (Vicar) on Aug 09, 2005 at 13:40 UTC
Re: My pattern for "in-place edit" for many files
by tphyahoo (Vicar) on Aug 09, 2005 at 14:40 UTC
    I like this, but in the version I just added to my toolbox I made one small change: die if there's nothing to replace in @ARGV. Otherwise this script just sits there waiting for STDIN. Being not all that wise about the diamond operator it took me a while to figure out what was going on.
    my @starters = @ARGV ? @ARGV : ('./beginning_includes'); #current di +rectory @ARGV = (); find sub { push @ARGV, $File::Find::name if $File::Find::name =~ /.txt$/i; # +or whatever condition here }, @starters; die "nothing to replace" unless @ARGV; }
Re: My pattern for "in-place edit" for many files
by tphyahoo (Vicar) on Aug 19, 2005 at 11:14 UTC
    Another possibility would be to use File::Searcher.

    UPDATE: Doesn't work too well on windows though. After mucking around a bit I decided to keep using simpler search and replace with $^I.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://115428]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2018-02-22 07:55 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (288 votes). Check out past polls.