为什么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*
它不会破坏符号链接。
答案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)等上使用...干杯,