web-dev-qa-db-ja.com

Sedインプレース編集により、ファイルのグループ所有権が変更されます

この方法でターゲットファイルとやり取りするシェル(php)スクリプトがあります。

  • ファイルとディレクトリがphpis_writable()で書き込み可能かどうかを検査します(これは問題ではないと思います)
  • sedコマンドを使用してインプレースファイル編集を行います。

grep -q "$search" "$passwd_file" && { sed -i "s|$search|$replace|" "$passwd_file"; printf "Password changed!\n"; } || printf "Password not changed!\n"

結果として、私は(他はすべて正しいが)myuser:www-data することが myuser:myuser

sedはファイルグループの所有権を変更しているように見えますが、可能であればそれを回避するにはどうすればよいですか?

8

sedのインプレース編集モード-iには少し問題があります。 sedは、同じディレクトリにsedy08qMAという一時ファイルを作成します。ここで、y08qMAはランダムに生成された文字列です。そのファイルは、元のファイルの変更された内容で埋められます。操作後、sedは元のファイルを削除し、一時ファイルの名前を元のファイル名に変更します。したがって、それは本当のinplace editではありません。呼び出し元ユーザーのアクセス許可と新しいiノード番号を含む新しいファイルを作成します。その振る舞いはほとんど悪くはありませんが、例えば、ハードリンクが壊れてしまいます。

ただし、trueインプレース編集が必要な場合は、edを使用する必要があります。 stdinからコマンドを読み取り、一時ファイルなしでファイルを直接編集します(これはedのメモリバッファに対して行われます)。一般的な方法は、printfを使用してコマンドリストを生成することです。

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file

printfコマンドは、次のような出力を生成します。

1,$s/search/replace/g
wq

これらの2行はedコマンドです。最初のものは文字列searchを検索し、それをreplaceに置き換えます。 2つ目は、ファイルへの変更を書き込み(w)、終了します(q)。 -sは診断出力を抑制します。

16
chaos

edの代わりにsedを使用することは、追加の入力をパイプする必要があることを考えると、これにはかなり不必要に思えます。現在取り組んでいるディストリビューション(CentOS 5.10)には、-cオプションがあり、sed-iオプションがあります。 _オプション。私はそれをテストしましたが、インライン編集を行うときに元の所有者とグループを維持しながら、完全に機能しました。変更時間は保持されません。

例:sed -ci -e '3,5d' file.txt

  • -cは、名前の変更ではなくコピーを使用します(つまり、所有権/グループを保持します)
  • -iインライン編集
  • -e実行するスクリプト/式

このオプションが他のディストリビューション全体でsedにどれだけ普及しているかはわかりません。 Solaris 10にはありませんでしたが、Solarisには欲しいものがたくさんありません。

2
d3vnulldroid