Como evito que o sed -i destrua links simbólicos?

21

Por que o sed -iexecutado no link simbólico destrói esse link e o substitui pelo arquivo de destino? Como evitar isso?

por exemplo.

$ 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 por que não é considerado um bug?

madneon
fonte

Respostas:

25

O sinalizador -i/ --in-placeedita um arquivo no local. Por padrão, sedlê o arquivo fornecido, processa a saída em um arquivo temporário e copia o arquivo temporário sobre o original, sem verificar se o original era um link simbólico.

O GNU sedtem uma --follow-symlinksbandeira, que faz com que se comporte como você deseja:

$ echo "cat" > pet
$ ln --symbolic pet pet_link
$ sed --in-place --follow-symlinks 's/cat/dog/' pet_link
$ cat pet
dog
Anko
fonte
6
Ele não edita um arquivo no local, mas edita uma cópia temporária do arquivo no diretório atual e depois move a cópia temporária sobre o original.
mikeserv
@mikeserv Ignorei os detalhes da implementação porque a pergunta era sobre a interface. É bom saber, obrigado!
Anko 28/03
1

Não é um bug, isso ocorre por design, uma vez que sedé um editor S tream ED , não um editor de arquivos. Basicamente, ele faz uma cópia e substitui o arquivo original pela cópia. BashFAQ

Como alternativa, você pode usar o excomando que possui sintaxe semelhante para substituição, por exemplo

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

ou vários arquivos:

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

Não destruirá os links simbólicos.

Relacionado: Como evito que o sed destrua hardinks?

kenorb
fonte
0

Acho que isso também funciona bem (preservando os links simbólicos e físicos):

sed 's/cat/dog/' pet_link > pet_link.tmp
cat pet_link.tmp > pet_link
rm pet_link.tmp
dashohoxha
fonte
0

Às vezes, há uma solução que usamos para gravar no mesmo arquivo que é lido. Aqui está um trecho da página de manual:

   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.

Aqui está um trecho que mostra que ele pode preservar links simbólicos, embora eu costumo usá-lo para preservar inodes:

# 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

que produz:

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

Em um sistema como:

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

O código da esponja está disponível em um pacote moreutils - alguns detalhes:

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

Em nossa loja, escrevemos uma versão que grava em um arquivo temporário para o caso de arquivos muito grandes.

O pacote está disponível no Debian, Fedora, macOS (via brew), etc.

drl
fonte