sed
一時ファイルを作成し、そのファイルに出力を書き込んでから、一時ファイルの名前を元のファイルの上に変更します。
何が起こるかを見ることができますstrace
:
$ strace -e trace=file sed -i -e '' a
execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0
<...trimmed...>
open("a", O_RDONLY) = 3
open("./sedxvhRY8", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("./sedxvhRY8", "a") = 0
+++ exited with 0 +++
これsed
により、すべてのファイル操作のログが記録されます。新しいファイルが(安全にO_CREAT|O_EXCL
)作成され、そこにデータが書き込まれ、元のファイルの上部に移動されますa
。
sed -i
バックアップに使用するサフィックスを受け入れます。その場合、元のファイルを最初に移動します(名前を変更するのではなく)。その引数は、ほとんどのBSDで必須sed
です。この場合、ディレクトリに正しい名前のファイルがまったくない場合があります。
perl
最近のバージョンでは、入力ファイルを開いてから削除し、同じ名前の新しいファイルを作成します。
open("a", O_RDONLY) = 3
unlink("a") = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
unlink
すでに開いているファイルを削除()すると、ハンドルを保持している間はそのファイルへのアクセスが保持されるため、削除されたファイルからデータを読み取ることができます。この方法でperl
は、一時ファイルではなく出力ファイルに直接書き込みます。追加のファイルは作成されませんが、プロセス中にファイルを読み取ると、sed
のアプローチとは異なり、部分的なコンテンツが取得されます。また、正しい名前のファイルがない場合もあります。これは、プロセスの最後ではなく、最初にあります(などsed -i .bak
)。
両方sed
とperl
:
- シンボリックリンクを通常のファイルに置き換えます。
- ハードリンクを解除します。
- 可能であれば、グループの所有権を保持します。
- デフォルトのグループ(または、そのディレクトリに
setgid
ビットがある場合は親ディレクトリのグループ)を使用してファイルを作成します。そのファイルが、自分が属しておらず、ルートではないグループによって所有されている場合です。
- rootの場合、ファイルの所有権を保持します。
- 基本的な権限を保持します。
- 結果のグループが開始時のグループと同じ場合は、保持
setuid
してsetgrp
ビットを保持します。
- スティッキービットを保持します。
- xattrsを保持しません。
sed
意志:
- ACLを保持します(Linuxの場合、他のユーザーについてはわかりません)。
perl
意志:
上記は、GNU sed
を搭載したLinux および(FreeBSDから派生した)を搭載したMac OS Xに当てはまりますsed
。