如何防止 sed 破坏硬链接?

如何防止 sed 破坏硬链接?

我的问题类似于如何防止 sed -i 破坏符号链接?,但涉及硬链接。

使用sed -i来处理文件会破坏该文件具有的所有硬链接,因为 sed 通过写入临时文件然后移动它来工作。该--follow-symlinks参数在硬链接的情况下没有帮助。

除了使用相当丑陋的方法之外,还有其他选择吗:

sed 's/cat/dog/' pet_link > pet_link

答案1

对于sed 's/cat/dog/'任何不改变文件大小的其他替换,使用任何类似 Bourne 的 shell,您可以执行以下操作:

sed 's/cat/dog/' < file 1<> file

鲜为人知但超过 35 岁的人标准 <>操作符是以读+写模式打开文件没有截断。基本上,这里将sed其输出写入其输入。确保输出不会覆盖文件中sed尚未读取的部分非常重要。

对于导致文件大小减小的替换,使用ksh93

sed 's/hippopotamus/ant/' < file 1<>; file

<>;ksh93扩展名与 相同,<>只是如果重定向的命令成功,文件将在命令完成的位置被截断。

或者使用 perl:

perl -pe 's/hippopotamus/ant/;
          END{truncate STDOUT, tell STDOUT}' < file 1<> file

对于其他任何事情,只需使用标准形式:

cp -i file file.back &&
  sed 's/dog/horse/g' < file.back > file # && rm -f file.back

1 尽管 Bourne shell 和 Korn shell 早期版本中的最初实现实际上已被破坏,但在 80 年代末已得到修复。 Almquist shell 最初并不支持它。

答案2

请注意,这sed是一个S特雷姆急诊科它,不是一个文件编辑器,因此人们倾向于滥用它来尝试编辑文件。基本上-i选项是非标准 FreeBSD 扩展(可能在其他操作系统上不可用),其次它不编辑文件 - 它会创建一个副本并用副本替换原始文件。Bash常见问题解答

另一种方法是使用edex具有类似语法的命令(Vim 的一部分),例如

ex +%s/cat/dog/e -scwq pet_link

或者按照@通配符推荐:

printf '%s\n' '%s/cat/dog/' x | ex pet_link

对于多个文件,您可以使用:

ex "+bufdo! %s/foo/bar/ge" -scxa **/*.lnk

如果你的 shell 支持一个新的通配选项(通过:启用shopt -s globstar),**在这种情况下使用将递归地工作。


了解更多POSIX语法,你可以尝试(按照@通配符建议):

for f in *.txt; do printf '%s\n' '%s/cat/dog/g' x | ex "$f"; done

或者:

find . -type f -exec sh -c 'for f; do printf "%s\n" "%s/cat/dog/g" x | ex "$f"; done' sh {} +

有关的:

答案3

一点儿ed

$ ed pet_link <<END_OF_ED
g/cat/s//dog/
w
END_OF_ED

这不会破坏硬链接。

答案4

我发现这效果很好(保留符号链接和硬链接):

sed 's/cat/dog/' pet_link > pet_link.tmp
cat pet_link.tmp > pet_link
rm pet_link.tmp

相关内容