Perl pie alternative Running on Cygwin, I cannot easily use perl -pi -e because it will always produce .bak files even though I don't want them. I wrote this script below to emulate perl -pi -e behavior and unlink the backup files after processing.

Also I wanted to simplify the call of the script. Instead of:

$ git ls-files | xargs perl -pi -e s/foo/bar/


I rather prefer to write

$ git ls-files | pie s/foo/bar


Although this program is not aimed to be particularly used with Git, with this alias pie="!git ls-files | pie" it becomes

$ git pie s/foo/bar


I feel this script can be simplified and the performances could be slightly improved. The question is how.

#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use File::Copy;

my $re = shift @ARGV;
@ARGV  = split(/\n/, do {local $/; &lt;stdin&gt;}) if @ARGV eq 0;

for my $file (@ARGV) {
    next unless -f $file;
    if (-f "$file.bak") {
        warn "[Warning] Backup file already exists and is been used by pie";
    }
    open my $fh,  "&lt;",  $file;
    open my $tmp, "&gt;", "$file.bak";
    while (&lt;$fh&gt;) {
        eval($re);
    } continue { print $tmp $_ }
    close $tmp;
    close $fh;
    move "$file.bak", $file;
}
Ok, here is a solution with no additional modules, moving eval out of the loop, and with few additional checks.

use strict;
use warnings;

$^I = '.bak';
my $re = shift @ARGV or die "Nothing to do..";
$re = eval "sub{ $re }" or die "Incorrect expression..";

chomp(@ARGV  = &lt;STDIN&gt;) if !@ARGV;
@ARGV = grep {
  warn "[Warning] Backup file already exists and is been used by pie"
    if -f "$_$^I";
  -f $_;
}
@ARGV;

my @bak = map "$_$^I", @ARGV;
while (&lt;&gt;) {
  $re-&gt;();
  print;
}
unlink(@bak);