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

I 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


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 -> /etc/nginx/sites-available/
lrwxrwxrwx 1 root root 61 Jun 11 17:26 -> /etc/nginx/sites-available/
lrwxrwxrwx 1 root root 54 Jun 11 17:26 -> /etc/nginx/sites-available/
lrwxrwxrwx 1 root root 54 Jun 11 17:26 -> /etc/nginx/sites-available/
lrwxrwxrwx 1 root root 55 Jun 11 17:26 -> /etc/nginx/sites-available/
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
-rw-r--r-- 1 root root 2618 Jun 13 16:24
-rw-r--r-- 1 root root  292 Jun 13 16:24
-rw-r--r-- 1 root root 2648 Jun 13 16:24
-rw-r--r-- 1 root root 3858 Jun 13 16:24
-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

Fig.01: sed is no longer destroying my symlinks on GNU/Linux

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 
 sed 's/foo/bar/g' < $i  1<> $i

Using third file

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

Using ed command

The syntax is:
$ ed -s link_file
Here is an example for multiple files done using bash for loop:

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

Using ex command

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

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

Using perl

The syntax is simple

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

You can tell Perl to use physical path by using realpath/readlink command.


You learned various command to prevent sed command overwriting symlinks. For more info read your local version of man pages of sed/bash/sh:
$ man sed
$ man bash
$ man ksh
$ man sh

🐧 Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or Weekly email newsletter.

🐧 1 comment so far... add one

CategoryList of Unix and Linux commands
File Managementcat
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
1 comment… add one
  • Sandro Oct 23, 2020 @ 16:39

    Caramba, muito boa a solução de abrir o arquivo para leitura e gravação com sed, eu nunca tinha visto uma combinação de redirecionamentos assim.
    Gostei muito, meus parabéns e muito obrigado.

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre> for code samples. Problem posting comment? Email me @