如何使用`perl -i`忽略只读文件?

And*_*all 12 perl file-io readonly

Perl的-i开关似乎修改了只读文件:

$ echo 'foobar' > tmp.txt
$ chmod -w tmp.txt
$ perl -pi -w -e 's/foobar/FOOBAR/' tmp.txt
$ cat tmp.txt
FOOBAR
Run Code Online (Sandbox Code Playgroud)

这是意外的,因为命令不应该能够根据其权限修改文件.预计,尝试通过其他方式更新它失败:

$ echo 'barbaz' > tmp.txt
-bash: tmp.txt: Permission denied
Run Code Online (Sandbox Code Playgroud)

为什么Perl修改只读文件(以及如何?),最重要的是:我怎样才能让Perl不这样做?

我能找到的唯一有用的信息资源是Perl FAQ:

文件的权限说明该文件中的数据可能发生什么....如果您尝试写入文件,则文件的权限控制您是否被允许.

这最终似乎说它不应该写它,因为文件系统说你做不到.

mob*_*mob 7

过滤@ARGV一个BEGIN块:

perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV} s/foobar/FOOBAR/' files
Run Code Online (Sandbox Code Playgroud)

现在,如果命令行上的所有文件都不可写,则为@ARGV空,ARGV文件句柄将尝试读取STDIN.我可以想到两种方法来避免这个问题:

  1. 关闭STDINBEGIN块,太

    perl -pi -e 'BEGIN{close STDIN;@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files
    
    Run Code Online (Sandbox Code Playgroud)
  2. 始终将此单行重定向输入称为 /dev/null

    perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files < /dev/null
    
    Run Code Online (Sandbox Code Playgroud)


cho*_*oba 6

请参阅perlrun中的文档:

重命名输入文件,按原始名称打开输出文件,并选择该输出文件作为print()语句的默认值

(......)

有关文件权限和-i问题的讨论,请参阅"为什么Perl让我删除只读文件?为什么-i clobber受保护文件?这不是Perl中的错误吗?" 在 perlfaq5.