Seiti Seiti - 3 months ago 5x
Perl Question

Is there a simple way to do bulk file text substitution in place?

I've been trying to code a Perl script to substitute some text on all source files of my project. I'm in need of something like:

perl -p -i.bak -e "s/thisgoesout/thisgoesin/gi" *.{cs,aspx,ascx}

But that parses all the files of a directory recursively.

I just started a script:

use File::Find::Rule;
use strict;

my @files = (File::Find::Rule->file()->name('*.cs','*.aspx','*.ascx')->in('.'));

foreach my $f (@files){
if ($f =~ s/thisgoesout/thisgoesin/gi) {
# In-place file editing, or something like that

But now I'm stuck. Is there a simple way to edit all files in place using Perl?

Please note that I don't need to keep a copy of every modified file; I'm have 'em all subversioned =)

Update: I tried this on Cygwin,

perl -p -i.bak -e "s/thisgoesout/thisgoesin/gi" {*,*/*,*/*/*}.{cs,aspx,ascx

But it looks like my arguments list exploded to the maximum size allowed. In fact, I'm getting very strange errors on Cygwin...


If you assign @ARGV before using *ARGV (aka the diamond <>), $^I/-i will work on those files instead of what was specified on the command line.

use File::Find::Rule;
use strict;

@ARGV = (File::Find::Rule->file()->name('*.cs', '*.aspx', '*.ascx')->in('.'));
$^I = '.bak';  # or set `-i` in the #! line or on the command-line

while (<>) {

This should do exactly what you want.

If your pattern can span multiple lines, add in a undef $/; before the <> so that Perl operates on a whole file at a time instead of line-by-line.