27

I cannot get in-place editing Perl one-liners running under ActivePerl to work unless I specify them with a backup extension:

C:\> perl -i -ape "splice (@F, 2, 0, q(inserted text)); $_ = qq(@F\n);" file1.txt
Can't do inplace edit without backup.

The same command with -i.bak or -i.orig works a treat but creates an unwanted backup file in the process.

Is there a way around this?

Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
Zaid
  • 35,070
  • 14
  • 81
  • 149

2 Answers2

35

This is a Windows/MS-DOS limitation. According to perldiag:

You're on a system such as MS-DOS that gets confused if you try reading from a deleted (but still opened) file. You have to say -i.bak, or some such.

Perl's -i implementation causes it to delete file1.txt while keeping an open handle to it, then re-create the file with the same name. This allows you to 'read' file1.txt even though it has been deleted and is being re-created. Unfortunately, Windows/MS-DOS does not allow you to delete a file that has an open handle attached to it, so this mechanism does not work.

Your best shot is to use -i.bak and then delete the backup file. This at least gives you some protection - for example, you could opt not to delete the backup if perl exits with a non-zero exit code. Something like:

perl -i.bak -ape "splice...." file1.txt && del file1.bak
rjh
  • 46,345
  • 3
  • 47
  • 60
  • So it is a Windows limitation. I was hoping that I wouldn't have to `unlink` the backup with a separate command... looks like I'll have to. Thanks for the help. – Zaid Apr 11 '10 at 11:59
  • Not entirely related, but in-place editing on sed in windows seems to work for me. I can see that your example wouldn't work in sed, but it might be helpful to know. – Mike Apr 10 '14 at 19:27
  • @Mike: On my end, `sed` in-place editing leaves temporary files like e.g. `sedGihEwg` in the file system - yours doesn't? Which version have you got? I'm using `GNU sed version 4.2.1`. – zb226 Oct 07 '16 at 08:26
  • @Zaid IMO it's a poo Perl implementation rather than a Windows limitation. If you port a program to another OS, your port has to account for the quirks of that OS, and Perl doesn't seem to bother in this case. – antred Feb 12 '18 at 12:52
  • 2
    And by poo I mean poor. Sorry. – antred Feb 12 '18 at 19:02
0

Sample with recursive modify and delete both done by find. Works on e.g. mingw git bash on windows.

$ find . -name "*.xml" -print0 | xargs -0 perl -p -i.bak -e 's#\s*<property name="blah" value="false" />\s*##g'
$ find . -name "*.bak" -print0 | xargs -0 rm

Binary terminated values passed between find/xargs to handle spaces. Unusual s/ prefix to avoid mangling xml in search term. This assumes you didn't have any .bak files hanging around to begin.

shuckc
  • 2,392
  • 19
  • 17