如何防止sed -i命令在Linux或Unix上覆盖我的符号链接

时间:2020-01-09 10:40:35  来源:igfitidea点击:

在Debian Linux服务器上运行了sed -i's/CONFIG_1/CONFIG_OPT_2/g'/etc/nginx/sites-enabled/*。 conf命令。
但是,sed命令破坏了链接并创建了一个常规文件来代替链接文件。
如何防止sed -i命令破坏Linux或类Unix系统上的符号链接?

sed命令编辑文件的-i或--in-place选项。
因此自然会破坏您的链接。

如何在符号链接上安全地使用sed -i命令,以防止sed破坏符号链接?

您必须将--follow-symlinks选项传递给GNU/sed命令,以便在就地处理时遵循符号链接。
语法为:

sed -i --follow-symlinks '...' input
sed -i --follow-symlinks 'regex' input

例子

让我们考虑一下/etc/nginx/sites-enabled中的以下文件:

$ cd /etc/nginx/sites-enabled/
$ ls -l

每个文件都是/etc/nginx/sites-available /目录中对应文件的符号链接。
如果运行以下命令,它将破坏所有内容:

$ cd /etc/nginx/sites-enabled/
$ sudo sed -i 's/192.168.1/192.168.1/g' *.conf
$ ls -l

输出示例:

drwxr-xr-x 2 root root 4096 Jun 13 16:24 ./
drwxr-xr-x 3 root root 4096 Jun 13 16:23 ../
lrwxrwxrwx 1 root root   34 Jun 13 16:23 default -> /etc/nginx/sites-available/default
-rw-r--r-- 1 root root  412 Jun 13 16:24 http.www.theitroad.org.conf
-rw-r--r-- 1 root root 2618 Jun 13 16:24 https.www.theitroad.org.conf
-rw-r--r-- 1 root root  292 Jun 13 16:24 http.www.theitroad.local.conf
-rw-r--r-- 1 root root 2648 Jun 13 16:24 https.dl.theitroad.local.conf
-rw-r--r-- 1 root root 3858 Jun 13 16:24 https.www.theitroad.local.conf
-rw-r--r-- 1 root root  158 Jun 13 16:24 longview.localhost.conf

为避免此类灾难,请在GNU/Linux sed版本上运行以下命令:

$ cd /etc/nginx/sites-enabled/
$ sudo sed -i --follow-symlinks 's/192.168.1/192.168.1/g' *.conf
$ ls -l

sed不再破坏我在GNU/Linux上的符号链接

处理BSD sed(macOS sed)

有多种方法可以处理非GNU/sed版本上的硬链接和软链接。
让我们看一些例子。

打开文件以使用sed进行读写

此语法应在具有GNU和非gnu版本的sed的ksh/sh/bash shell上运行:

## replace foo with bar using any version of sed
## Each file opened using the redirection operator: 
## [n]<>word syntax
sed 's/foo/bar/g' < input  1<> input
 
##
## 或者
##
for i in /path/to/dir/*.conf 
do
sed 's/foo/bar/g' < $i  1<> $i
done

使用第三个文件

尝试以下语法:

$ cp myfile myfile.bak
$ sed 's/foo/bar/g' < myfile.bak > myfile
$ rm -f file.bak

使用ed命令

语法为:

$ ed -s link_file

这是使用bash for loop完成的多个文件的示例:

for i in /path/to/dir/*.conf 
do
ed -s $i <<< $',s/foo/bar/g\nw'
done

使用ex命令

语法为:

$ ex +%s/foo/bar/e -scwq file_link

或者

for i in /path/to/dir/*.conf 
do
ex +%s/foo/bar/e -scwq $i
done

使用Perl

语法很简单

perl -p -i -e 's/foo/bar/g' $(readlink -f file_link)
## 或者
perl -p -i -e 's/foo/bar/g' $(realpath file_link)

您可以使用realpath/readlink命令告诉Perl使用物理路径。