How is the inplace modification of a file being done?

Jim*_*Jim 11 sed perl files

文件的“就地”修改是什么意思,例如通过sed -iperl -i意味着什么?
我的问题是关于这种就地修改是如何完成的。是复制的文件是在副本中进行修改然后替换原来的吗?或者原始文件是否以某种方式被修改到​​位?

Mic*_*mer 19

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 +++
Run Code Online (Sandbox Code Playgroud)

这会记录所有文件操作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
Run Code Online (Sandbox Code Playgroud)

当您删除 ( unlink) 已打开的文件时,只要您保留句柄,您就可以保留对其的访问权限,因此它可以继续从已删除的文件中读取数据。以这种方式perl直接写入输出文件,而不是写入临时文件:不会创建其他文件,但是如果您在此过程中读取文件,您将获得部分内容,这与 withsed的方法不同。还有一小段时间没有具有正确名称的文件,这是在过程的开始而不是结束(如sed -i .bak)。


双方sedperl会:

  • 用普通文件替换符号链接。
  • 打破硬链接。
  • 如果可能,保留组所有权。
  • 如果该文件setgid由您不在其中且您不是 root 的组拥有,则使用您的默认组(或父目录的组,如果该目录具有该位)创建该文件。
  • 如果您是 root,请保留文件所有权。
  • 保留基本权限。
  • 保留setuidsetgrp位,如果结果组与它开始的组相同。
  • 保留粘性位。
  • 保留 xattrs。

sed 将要:

  • 保留 ACL (在 Linux 上;我不知道其他人)

perl 将要:

  • 保留 ACL。

以上在带有 GNU 的 Linuxsed和带有它的 (FreeBSD-derived) 的 Mac OS X上都是正确的sed