Как предупредить sed -i от уничтожения символических ссылок?

Почему 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 

И почему это не считается ошибкой?

Флаг -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 

Это не ошибка, это по дизайну, так как sed – это S tream ED itor, а не редактор файлов. Он в основном делает копию и заменяет исходный файл копией. BashFAQ

В качестве альтернативы вместо этого вы можете использовать команду ex которая имеет аналогичный синтаксис для подстановки, например

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

или несколько файлов:

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

Он не уничтожит символические ссылки.

Связано: Как я могу предотвратить sed от уничтожения hardinks?