Wie verhindere ich, dass sed -i Symlinks zerstört?

21

Warum zerstört die sed -iAusführung von symlink diesen Link und ersetzt ihn durch die Zieldatei? Wie vermeide ich das?

z.B.

$ 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

Und warum wird es nicht als Fehler angesehen?

Madneon
quelle

Antworten:

25

Das Flag -i/ --in-placebearbeitet eine Datei an Ort und Stelle. sedLiest standardmäßig die angegebene Datei, verarbeitet die Ausgabe in eine temporäre Datei und kopiert die temporäre Datei über das Original, ohne zu überprüfen, ob das Original ein Symlink war.

GNU sedhat ein --follow-symlinksFlag, mit dem es sich so verhält, wie Sie es möchten:

$ echo "cat" > pet
$ ln --symbolic pet pet_link
$ sed --in-place --follow-symlinks 's/cat/dog/' pet_link
$ cat pet
dog
Anko
quelle
6
Eine Datei wird nicht direkt bearbeitet, sondern eine temporäre Kopie der Datei im aktuellen Verzeichnis wird bearbeitet. Diese temporäre Kopie wird dann über das Original verschoben.
mikeserv
@mikeserv Ich habe die Implementierungsdetails übersprungen, weil es um die Benutzeroberfläche ging. Gut zu wissen, danke!
Anko
1

Es ist kein Fehler, dies ist beabsichtigt, da sedes sich um einen S tream- ED- Editor handelt, nicht um einen Datei-Editor. Grundsätzlich wird eine Kopie erstellt und die Originaldatei durch die Kopie ersetzt. BashFAQ

Alternativ können Sie auch einen exBefehl verwenden, der eine ähnliche Syntax für die Ersetzung aufweist, z

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

oder mehrere Dateien:

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

Die symbolischen Links werden nicht zerstört.

Siehe auch : Wie verhindere ich, dass sed Hardinks zerstört?

Kenorb
quelle
0

Ich finde, dass dies auch gut funktioniert (wobei sowohl symbolische als auch harte Links erhalten bleiben):

sed 's/cat/dog/' pet_link > pet_link.tmp
cat pet_link.tmp > pet_link
rm pet_link.tmp
Dashohoxha
quelle
0

Es gibt eine Lösung, die wir manchmal verwenden, um in dieselbe Datei zu schreiben, aus der gelesen wird. Hier ist ein Auszug aus der Manpage:

   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.

Hier ist ein Ausschnitt, der zeigt, dass symbolische Verknüpfungen erhalten bleiben können, obwohl ich ihn normalerweise verwende, um Inodes zu erhalten:

# 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

welche produziert:

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

Auf einem System wie:

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

Der Schwammcode ist im Paket moreutils enthalten - einige Details:

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

In unserem Shop haben wir eine Version geschrieben, die bei sehr großen Dateien in eine temporäre Datei schreibt.

Das Paket ist auf Debian, Fedora, macOS (via brew) usw. verfügbar.

drl
quelle