12

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

$ echo 'foobar' > tmp.txt
$ chmod -w tmp.txt
$ perl -pi -w -e 's/foobar/FOOBAR/' tmp.txt
$ cat tmp.txt
FOOBAR

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

$ echo 'barbaz' > tmp.txt
-bash: tmp.txt: Permission denied

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

我能在这方面找到的唯一一些信息资源是Perl FAQ

文件的权限说明了该文件中的数据会发生什么。…如果您尝试写入文件,则文件的权限决定您是否被允许。

最终似乎它说它应该能够写入它,因为文件系统说你不能。

4

3 回答 3

7

@ARGV在一个BEGIN块中过滤:

perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV} s/foobar/FOOBAR/' files

现在,如果命令行上没有可写的文件,@ARGV则将为空,并且ARGV文件句柄将尝试从STDIN. 我可以想出两种方法来避免这个问题:

  1. STDIN也在BEGIN街区关闭

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

    perl -pi -e 'BEGIN{@ARGV=grep{-w $_}@ARGV}s/foobar/FOOBAR/' files < /dev/null
    
于 2013-04-03T15:46:22.487 回答
6

请参阅perlrun中的文档:

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

(...)

有关文件权限和 -i 问题的讨论,请参阅“为什么 Perl 允许我删除只读文件?为什么 -i 会破坏受保护的文件?这不是 Perl 中的错误吗?” 在 perlfaq5中。

于 2013-04-03T15:37:55.940 回答
3

perlrun

-i
指定由 <> 构造处理的文件将被就地编辑。它通过重命名输入文件、按原始名称打开输出文件并选择该输出文件作为 print() 语句的默认文件来实现这一点。

所以它并没有真正修改文件。它将文件移开(需要目录写入权限,而不是文件写入权限),然后使用旧名称创建一个新文件。

我怎样才能让 Perl 不这样做?

我不认为你可以在使用-i.

于 2013-04-03T15:36:16.023 回答