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。これが問題にならないようにするには、次の 2 つの方法が考えられます。

  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 に答える