Come posso impedire a sed -i di distruggere i symlink?


21

Perché sed -ieseguito su symlink distrugge quel collegamento e lo sostituisce con il file di destinazione? Come evitarlo?

per esempio.

$ 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

E perché non è considerato un bug?

Risposte:


25

Il flag -i/ --in-placemodifica un file in atto. Per impostazione predefinita, sedlegge il file specificato, lo elabora in uscita in un file temporaneo, quindi copia il file temporaneo sull'originale, senza verificare se l'originale fosse un collegamento simbolico.

GNU sedha un --follow-symlinksflag, che lo fa comportare come vuoi:

$ echo "cat" > pet
$ ln --symbolic pet pet_link
$ sed --in-place --follow-symlinks 's/cat/dog/' pet_link
$ cat pet
dog

6
Non modifica un file sul posto, ma modifica una copia temporanea del file nella directory corrente, quindi sposta quella copia temporanea sull'originale.
Mikeserv,

@mikeserv Ho saltato i dettagli dell'implementazione perché la domanda riguardava l'interfaccia. Buono a sapersi, grazie!
Anko,

1

Non è un bug, questo è di progettazione in quanto sedè un S tream ED itor, non un editor di file. Fondamentalmente crea una copia e sostituisce il file originale con la copia. BashFAQ

In alternativa puoi usare il excomando che ha una sintassi simile per la sostituzione, ad es

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

o più file:

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

Non distruggerà i collegamenti simbolici.

Correlati: Come posso impedire a sed di distruggere gli hardink?


0

Trovo che anche questo funzioni bene (preservando sia i collegamenti simbolici che quelli reali):

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

0

C'è una soluzione che a volte usiamo per scrivere nello stesso file da cui viene letto. Ecco un estratto dalla pagina 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.

Ecco uno snippet che mostra che può conservare i collegamenti simbolici, anche se di solito lo uso per preservare gli 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

che produce:

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

Su un sistema come:

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

Il codice spugna è disponibile in un pacchetto moreutils - alcuni dettagli:

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

Nel nostro negozio, abbiamo scritto una versione che scrive in un file temporaneo per il caso di file molto grandi.

Il pacchetto è disponibile su Debian, Fedora, macOS (via brew), ecc ... evviva,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.