如何防止 sed -i 破坏符号链接?

如何防止 sed -i 破坏符号链接?

为什么sed -i在符号链接上执行会破坏该链接并将其替换为目标文件?如何避免这种情况?

例如。

$ ls -l pet*
-rw-rw-r-- 1 madneon madneon 4 mar 23 16:46 pet
lrwxrwxrwx 1 madneon madneon 6 mar 23 16:48 pet_link -> pet

$ sed -i 's/cat/dog/' pet_link

$ ls -l pet*
-rw-rw-r-- 1 madneon madneon 4 mar 23 16:48 pet
-rw-rw-r-- 1 madneon madneon 4 mar 23 16:49 pet_link

为什么它不被视为错误?

答案1

-i/标志--in-place就地编辑文件。默认情况下,sed读取给定文件,将其处理输出到临时文件中,然后将临时文件复制到原始文件上,而不检查原始文件是否是符号链接。

GNUsed有一个--follow-symlinks标志,可以让它按照你想要的方式运行:

$ echo "cat" > pet
$ ln --symbolic pet pet_link
$ sed --in-place --follow-symlinks 's/cat/dog/' pet_link
$ cat pet
dog

答案2

这不是一个错误,这是设计使然,sed因为S特雷姆急诊科itor,不是文件编辑器。它基本上会制作一个副本并用副本替换原始文件。Bash常见问题解答

或者,您可以使用ex命令来代替,它具有类似的替换语法,例如

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

或多个文件:

ex "+bufdo! %s/cat/dog/ge" -scxa **/pet_link*

它不会破坏符号链接。

有关的:如何防止 sed 破坏 Hardink?

答案3

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

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

答案4

有时我们会使用一种解决方案来写入与读取的文件相同的文件。以下是手册页的摘录:

   sponge reads standard input and writes it out to the specified file.
   Unlike a shell redirect, sponge soaks up all its input before opening
   the output file. This allows constructing pipelines that read from and
   write to the same file.

   It also creates the output file atomically by renaming a temp file into
   place, and preserves the permissions of the output file if it already
   exists. If the output file is a special file or symlink, the data will
   be written to it.

这是一个片段,显示它可以保留符号链接,尽管我通常使用它来保留索引节点:

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

rm -f pet pet_link
echo "cat" > pet
pl " Input data file $FILE:"
head -v pet

pl " Results, before sed:"
ln --symbolic pet pet_link
ls -ligG pet pet_link
# sed --in-place --follow-symlinks 's/cat/dog/' pet_link
pe
pe " Results, after sed:"
sed 's/cat/dog/' pet_link | sponge pet_link
head -v pet
ls -ligG pet pet_link

其产生:

-----
 Input data file data1:
==> pet <==
cat

-----
 Results, before sed:
1571283 -rw-r--r-- 1 4 Nov 26 23:03 pet
1571286 lrwxrwxrwx 1 3 Nov 26 23:03 pet_link -> pet

 Results, after sed:
==> pet <==
cat
1571283 -rw-r--r-- 1 4 Nov 26 23:03 pet
1571286 lrwxrwxrwx 1 3 Nov 26 23:03 pet_link -> pet

在这样的系统上:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30

海绵码有包装更多实用程序-- 一些细节:

sponge  soak up standard input and write to a file (man)
Path    : /usr/bin/sponge
Package : moreutils
Home    : http://kitenet.net/~joey/code/moreutils/
Version : 0.52
Type    : ELF 64-bit LSB executable, x86-64, version 1 (SYS ...)

在我们的商店,我们编写了一个版本,可以在文件非常大的情况下写入临时文件。

该软件包可在 Debian、Fedora、macOS(通过brew)等上使用...干杯,

相关内容