7
\$\begingroup\$

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 $/; <stdin>}) 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,  "<",  $file;
    open my $tmp, ">", "$file.bak";
    while (<$fh>) {
        eval($re);
    } continue { print $tmp $_ }
    close $tmp;
    close $fh;
    move "$file.bak", $file;
}                          
\$\endgroup\$
2
  • \$\begingroup\$ Why don't you just delete .bak files created by perl -i.bak -pe..? \$\endgroup\$
    – mpapec
    Commented Aug 28, 2015 at 7:46
  • \$\begingroup\$ @mpapec It is basically what I do! The idea is to shorten the writing as well. With this I can avoid using xargs \$\endgroup\$
    – nowox
    Commented Aug 29, 2015 at 10:26

1 Answer 1

2
\$\begingroup\$

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  = <STDIN>) 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 (<>) {
  $re->();
  print;
}
unlink(@bak);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.