perl -iがシンボリックリンクを壊さないようにする方法はありますか?

perl -iがシンボリックリンクを壊さないようにする方法はありますか?

私の友人はこうすると、次のように指摘しました。

perl -pi.bak -e 's/foo/bar/' somefile

"somefile"が実際にシンボリックリンクである場合、Perlは文書に記載されているように正確に実行します。

入力ファイルの名前を変更し、元の名前で出力ファイルを開き、その出力ファイルをprint()ステートメントのデフォルトファイルとして選択してこれを行います。拡張子(提供されている場合)は、バックアップコピーを作成するために古いファイルの名前を変更するために使用されます。 [...]

これにより、変更されていない物理ファイルを指す新しいシンボリックリンク「somefile.bak」と、変更を含む新しく変更された一般ファイル「somefile」が生成されます。

ほとんどの場合、シンボリックリンクに従うのが望ましい動作です(.bakファイルの正しい場所が不明になっても)。ラッパーでシンボリックリンクをテストし、状況を適切に処理する以外にこれを行う簡単な方法はありますか?

sed価値があるだけ同じことを行います。)

答え1

小さいか知りたいsponge汎用ユーティリティ(「標準入力を受け取りファイルに書き込む」)その他のユーティリティこの場合、シンボリックリンクに従うかどうかが役に立ちます。

作家説明する spongeこのように:

Unixツールを使用してファイルを内部編集するときに発生する問題を解決します。つまり、編集したいファイルに出力をリダイレクトすると、パイプラインの最初のコマンドが実行される前にリダイレクトが適用されます(ファイル内容の破損)。これでファイルを読む時間です。と同じsed -iスイッチを使用perl -iすると、この問題を解決できますが、パイプラインで使用したいすべてのコマンドにこれらのオプションがあるわけではなく、とにかくマルチコマンドパイプラインではその方法を使用できません。

私は通常、次のスポンジを使用します。

sed '...' file | grep '...' | sponge file

答え2

シンボリックリンクが存在することを知っている場合は、次のようにsomefileファイルのフルパスを明示的に提供できます。

perl -pi.bak -e 's/foo/bar/' $(readlink somefile)

これにより、元のファイルを使用して交換が直接行われるため、元のシンボリックリンクは変更されていません。

答え3

単一ファイルを処理する場合、コマンドは次のようになります。

perl -i -pe'...' -- "$qfn"

これで解決策は次のようになります。

perl -i -pe'...' -- "$( readlink -e -- "$qfn" )"

これはシンボリックリンクと非シンボルリンクの両方を扱います。


ランダムに多数のファイルを処理する場合、コマンドは次のようになります。

... | xargs -r perl -i -pe'...' --

これで解決策は次のようになります。

... | xargs -r readlink -ze -- | xargs -r0 perl -i -pe'...' --

これはシンボリックリンクと非シンボルリンクの両方を扱います。


警告する readlink標準コマンドではないため、そのコマンドの存在、パ​​ラメーター、および機能がシステムによって異なるため、マニュアルを確認してください。たとえば、一部の実装には-f(ここでも使用できます) がありますが、そうでない場合もあり-e、両方がない場合もあります。busybox動作はreadlink -fGNUに似ていますreadlink -e。一部のシステムには通常、 GNUのrealpathようreadlinkに動作するコマンドがありますreadlink -f

GNUを使用すると、readlink -e既存のファイルとして解釈できないシンボリックリンクは自動的に削除されます。

関連情報