Modifying a File in Place with -i Switch

Problem

You need to modify a file in place from the command line, and you’re too lazy[14] for the file manipulation of Section 7.8.

Solution

Use the -i and -p switches to Perl. Write your program on the command line:

% perl -i.orig -p -e 'FILTER COMMAND' file1 file2 file3 ...

Or use the switches in programs:

#!/usr/bin/perl -i.orig -p
# filter commands go here

Discussion

The -i command-line switch modifies each file in place. It creates a temporary file as in the previous recipe, but Perl takes care of the tedious file manipulation for you. Use it with -p (explained in Section 7.7) to turn:

while (<>) {
    if ($ARGV ne $oldargv) {           # are we at the next file?
        rename($ARGV, $ARGV . '.orig');
        open(ARGVOUT, ">$ARGV");       # plus error check
        select(ARGVOUT);
        $oldargv = $ARGV;
    }
    s/DATE/localtime/e;
}
continue{
    print;
}
select (STDOUT);                      # restore default output

into:

% perl -pi.orig -e 's/DATE/localtime/e'

The -i switch takes care of making a backup (say -i instead of -i.orig to discard the original file contents instead of backing them up), and -p makes Perl loop over filenames given on the command line (or STDIN if no files were given).

The preceding one-liner would turn a file containing the following:

Dear Sir/Madam/Ravenous Beast,
    As of DATE, our records show your account
is overdue.  Please settle by the end of the month.
Yours in cheerful usury,
    --A. Moneylender

into:

Dear Sir/Madam/Ravenous Beast, As of Sat Apr 25 12:28:33 1998, our records show your account ...

Get Perl Cookbook now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.