Jak zapobiec niszczeniu dowiązań symbolicznych przez sed -i?

21

Dlaczego sed -iwykonanie na dowiązaniu symbolicznym niszczy to łącze i zastępuje je plikiem docelowym? Jak tego uniknąć?

na przykład.

$ 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 dlaczego nie jest to uważane za błąd?

madneon
źródło

Odpowiedzi:

25

The -i/ --in-placeFlaga edytuje plik w miejscu. Domyślnie sedodczytuje podany plik, przetwarza go na plik tymczasowy, a następnie kopiuje plik tymczasowy na oryginał, nie sprawdzając, czy oryginał był dowiązaniem symbolicznym.

GNU sedma --follow-symlinksflagę, która sprawia, że ​​zachowuje się tak, jak chcesz:

$ echo "cat" > pet
$ ln --symbolic pet pet_link
$ sed --in-place --follow-symlinks 's/cat/dog/' pet_link
$ cat pet
dog
Anko
źródło
6
Nie edytuje pliku w miejscu, ale edytuje tymczasową kopię pliku w bieżącym katalogu, a następnie przenosi tę tymczasową kopię na oryginał.
mikeserv
@ Mikeserv Pominąłem szczegóły implementacji, ponieważ pytanie dotyczyło interfejsu. Dobrze wiedzieć, dzięki!
Anko
1

To nie jest błąd, sedjest to zgodne z projektem, ponieważ jest to wersja S tream ED , a nie edytor plików. Zasadniczo tworzy kopię i zastępuje oryginalny plik kopią. BashFAQ

Zamiast tego możesz użyć expolecenia, które ma podobną składnię do podstawienia, np

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

lub wiele plików:

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

Nie zniszczy symbolicznych linków.

Powiązane: Jak zapobiec sed niszczyć hardinks?

kenorb
źródło
0

Uważam, że to również działa dobrze (zachowując zarówno dowiązania symboliczne, jak i twarde):

sed 's/cat/dog/' pet_link > pet_link.tmp
cat pet_link.tmp > pet_link
rm pet_link.tmp
dashohoxha
źródło
0

Istnieje rozwiązanie, którego czasami używamy do zapisu do tego samego pliku, z którego jest on odczytywany. Oto fragment strony 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.

Oto fragment kodu, który pokazuje, że może zachować dowiązania symboliczne, chociaż zwykle używam go do zachowania i-węzłów:

# 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

który produkuje:

-----
 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

W systemie takim jak:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30

Kod gąbki jest dostępny w pakiecie moreutils - niektóre szczegóły:

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 ...)

W naszym sklepie napisaliśmy wersję, która zapisuje plik tymczasowy w przypadku bardzo dużych plików.

Pakiet jest dostępny na Debianie, Fedorze, macOS (poprzez napar) itp. ... Pozdrawiam,

drl
źródło