Perl’s -i
switch appears to modify read-only files:
$ echo 'foobar' > tmp.txt
$ chmod -w tmp.txt
$ perl -pi -w -e 's/foobar/FOOBAR/' tmp.txt
$ cat tmp.txt
FOOBAR
This is unexpected, as the command should not have been able to modify the file per its permissions. Expectedly, trying to update it via other means fails:
$ echo 'barbaz' > tmp.txt
-bash: tmp.txt: Permission denied
Why is Perl modifying read-only files (and how?), and, most importantly: how can I get Perl to not do so?
The only somewhat informative resource I can find on this is in the Perl FAQ:
The permissions on a file say what can happen to the data in that file. … If you try to write to the file, the permissions of the file govern whether you're allowed to.
Which ultimately seems like its saying it shouldn’t be able to write to it, since the file system says you cannot.
Filter @ARGV
in a BEGIN
block:
perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV} s/foobar/FOOBAR/' files
Now if none of the files on the command line are writable, @ARGV
will be empty and the ARGV
filehandle will try to read from STDIN
. I can think of two ways to keep this from being a problem:
Close STDIN
in the BEGIN
block, too
perl -pi -e 'BEGIN{close STDIN;@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files
Always call this one-liner redirecting input from /dev/null
perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files < /dev/null
See the documentation in perlrun:
renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements
(...)
For a discussion of issues surrounding file permissions and -i, see "Why does Perl let me delete read-only files? Why does -i clobber protected files? Isn't this a bug in Perl?" in perlfaq5.
From perlrun:
-i
specifies that files processed by the <> construct are to be edited in-place. It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements.
So it is doesn't really modify the file. It moves the file out of the way (which requires directory write permissions, not file write permissions) and then creates a new one with the old name.
how can I get Perl to not do so?
I don't think you can when you use -i
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With