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


21

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

例如。

$ 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

为什么不将其视为错误?

Answers:


25

-i/ --in-place标记编辑到位的文件。默认情况下,sed读取给定文件,将其处理成一个临时文件,然后将该临时文件复制到原始文件上,而无需检查原始文件是否为符号链接。

GNU sed有一个--follow-symlinks标志,可以使其表现为您想要的:

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

6
它不会在适当位置编辑文件,而是在当前目录中编辑该文件的临时副本,然后将该临时副本移到原始目录上。
mikeserv

@mikeserv我跳过了实现细节,因为问题是关于接口的。很高兴知道,谢谢!
Anko 2015年

1

这不是错误,这是设计使然,因为sed它是S tream ED监视器,而不是文件编辑器。它基本上是制作副本,并用副本替换原始文件。Bash常见问题

或者,您可以改用ex具有相似语法的替代命令,例如

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

或多个文件:

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

它不会破坏符号链接。

相关:如何防止sed破坏硬墨水?


0

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

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

0

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

   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.

这是一个片段,表明它可以保留符号链接,尽管我通常使用它来保留inode:

# 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

海绵代码可在moreutils软件包中找到 -一些详细信息:

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)等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.