ファイルを引数として受け入れ、ファイルを変更して、2番目の引数で指定されたファイル名に書き込むコマンドがあります。そのプログラムをmodifyfile
と呼びます。
「そのまま」動作するようにしたいので、一時ファイルに変更してから戻すシェルスクリプト(bash)を作成しました。
TMP=`mktemp`
modifyfile "$original" "$TMP"
mv -v "$TMP" "$original"
これには、このファイルの権限を破壊するという残念な副作用があります。ファイルはデフォルトの権限で再作成されます。
mv
コマンドに、アクセス許可を変更せずに宛先を上書きするように指示する方法はありますか?または、元のユーザー、グループ、および権限を保存して復元する方法はありますか?
mv
を使用する代わりに、cat
をリダイレクトするだけです。例えば:
TMP=$(mktemp)
modifyfile "$original" "$TMP"
cat "$TMP" > "$original"
これにより、$original
が$TMP
の内容で上書きされ、ファイルレベルでは何も変更されません。
ファイルを新しいバージョンで置き換える方法は2つあります。
新しいバージョンで一時ファイルを作成し、適切な場所に移動します。
古いファイルを上書きします。
可能であれば、方法1を使用しますが、最初に元のファイルの属性をcp -p --attributes-only
で複製します。これにはGNU coreutilsが必要です(つまり、非組み込みLinux、または十分にLinuxに似た環境)。cp
に--attributes-only
がない場合は、このオプションを省略してください:動作しますが、データも複製されます。
tmp=$(mktemp)
cp -p --attributes-only "$original" "$tmp"
modifyfile "$original" "$tmp"
mv -f "$tmp" "$original"
既存のファイルの属性を複製できない場合(たとえば、ファイルに対する書き込み権限はあるが所有しておらず、所有者を保持したい場合)は、方法2のみが可能です。データ損失のリスクを最小限に抑えるには:
tmp=$(mktemp)
backup="${original}~"
modifyfile "$original" "$tmp"
cp -p "$original" "$backup"
cp -f "$tmp" "$original"
最初の回答について話し合った後、別の回答を提案します。
_TMP="$(mktemp "$original".XXXXXXXXXX)"
modifyfile "$original" "$TMP"
chmod --reference="$original" "$TMP"
chown --reference="$original" "$TMP"
mv -f "$TMP" "$original"
_
備考:
$original
_ではなく_/tmp
_と同じフォルダーに配置されるように、mktemp
テンプレートで_$original
_を使用しています。 _/tmp
_が別のファイルシステムにマウントされている場合、操作はアトミックではなくなると思います。mktemp
の結果が引用されるようになりました。$()
を使用しています。ch{mod,own} --reference
_は、_$original
_の権限を_$TMP
_に転送するために使用されます。誰かがメタデータで転送できる、また転送すべきであるという追加のアイデアを持っている場合は、投稿を編集して追加してください。