Як запобігти sed -i знищувати символьні посилання?


21

Чому 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

І чому це не вважається помилкою?

Відповіді:


25

-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

6
Він не редагує файл на місці, але редагує тимчасову копію файлу в поточному каталозі, після чого переміщує цю темп-копію над оригіналом.
mikeserv

@mikeserv Я пропустив деталі реалізації, оскільки питання стосувалося інтерфейсу. Приємно знати, хоча!
Анко

1

Це не помилка, це за задумом, оскільки 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-файлів?


0

Я вважаю, що це також добре працює (зберігаючи як символічні, так і жорсткі посилання):

sed 's/cat/dog/' pet_link > pet_link.tmp
cat pet_link.tmp > pet_link
rm pet_link.tmp

0

Є рішення, яке ми іноді використовуємо для запису в той самий файл, з якого читається. Ось уривок зі сторінки man:

   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.

Ось фрагмент, який показує, що він може зберігати символьні посилання, хоча я зазвичай використовую його для збереження inode:

# 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

Код губки доступний в упаковці moreutils - деякі деталі:

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 (через вариво) тощо ... ура,

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.