How to prevent sed -i command overwriting my symlinks on Linux or Unix

How to prevent sed -i command overwriting my symlinks on Linux or Unix

recently ran a command ‘sed -i 's/CONFIG_1/CONFIG_OPT_2/g' /etc/nginx/sites-enabled/*.conf‘ on a Debian Linux server. However, the sed command destroyed the link and created a regular file in place of the link file. How can I prevent my ‘sed -i’ command from destroying symlinks on Linux or Unix-like system?

The -i or --in-place option for sed command edit files in place. So naturally it is going to destroy your links.

How do I use ‘sed -i’ command safely on symbolic links to prevent sed from destroying symlinks?

You must pass the --follow-symlinks option to the GNU/sed command to follow symlinks when processing in place. The syntax is:
sed -i --follow-symlinks '...' input
sed -i --follow-symlinks 'regex' input

Example

Let us consider the following files in /etc/nginx/sites-enabled:
$ cd /etc/nginx/sites-enabled/
$ ls -l

Sample outputs:

lrwxrwxrwx 1 root root 34 Jun 11 13:44 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 61 Jun 11 17:26 http.www.linuxmasterswiki.org.conf -> /etc/nginx/sites-available/http.www.linuxmasterswiki.org.conf
lrwxrwxrwx 1 root root 61 Jun 11 17:26 https.www.linuxmasterswiki.org.conf -> /etc/nginx/sites-available/https.origin-cdn.linuxmasterswiki.org.conf
lrwxrwxrwx 1 root root 54 Jun 11 17:26 http.www.linuxmasterswiki.com.biz.conf -> /etc/nginx/sites-available/http.www.linuxmasterswiki.biz.conf
lrwxrwxrwx 1 root root 54 Jun 11 17:26 https.dl.linuxmasterswiki.biz.conf -> /etc/nginx/sites-available/https.dl.linuxmasterswiki.biz.conf
lrwxrwxrwx 1 root root 55 Jun 11 17:26 https.www.linuxmasterswiki.biz.conf -> /etc/nginx/sites-available/https.www.linuxmasterswiki.biz.conf
lrwxrwxrwx 1 root root 50 Jun 11 17:39 longview.localhost.conf -> /etc/nginx/sites-available/longview.localhost.conf

Each file is a symlink to corresponding file in /etc/nginx/sites-available/ directory. If you run the following command it will destroy everything:
$ cd /etc/nginx/sites-enabled/
$ sudo sed -i 's/192.168.1/192.168.2/g' *.conf
$ ls -l

Sample outputs:

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.linuxmasterswiki.org.conf
-rw-r--r-- 1 root root 2618 Jun 13 16:24 https.www.linuxmasterswiki.org.conf
-rw-r--r-- 1 root root  292 Jun 13 16:24 http.www.linuxmasterswiki.biz.conf
-rw-r--r-- 1 root root 2648 Jun 13 16:24 https.dl.linuxmasterswiki.biz.conf
-rw-r--r-- 1 root root 3858 Jun 13 16:24 https.www.linuxmasterswiki.biz.conf
-rw-r--r-- 1 root root  158 Jun 13 16:24 longview.localhost.conf

To avoid such disaster run the following command on GNU/Linux sed version:
$ cd /etc/nginx/sites-enabled/
$ sudo sed -i --follow-symlinks 's/192.168.1/192.168.2/g' *.conf
$ ls -l

Dealing with BSD sed (macOS sed)

There are various ways to deal with hard links and softlinks on non GNU/sed version. Let us see a few examples.

Open file for reading and writing with sed

This syntax should work on ksh/sh/bash shell with both GNU and non-gnu version of sed:

## 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
 
##
## OR ##
##
for i in /path/to/dir/*.conf 
do
 sed 's/foo/bar/g' < $i  1<> $i
done

Using third file

Try the following syntax:
$ cp myfile myfile.bak
$ sed 's/foo/bar/g' < myfile.bak > myfile
$ rm -f file.bak

Using ed command

The syntax is:
$ ed -s link_file <<< $',s/foo/bar/g\nw'

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

Using ex command

The syntax is:
$ ex +%s/foo/bar/e -scwq file_link
OR

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

For more info read your local version of man pages of sed/bash/sh:
$ man sed
$ man bash
$ man ksh
$ man sh

 
Enjoyed this video?
How to prevent sed -i command overwriting my symlinks on Linux or Unix
"No Thanks. Please Close This Box!"