O redirecionamento de arquivos Bash funciona de maneira diferente do script

1
$ cat test.txt
foo
bar

Este comando sed substitui a primeira linha em text.txt por "baz". Funciona bem a partir da linha de comando:

$ sed "1s%.*%baz%" "test.txt" > "test.txt"
$ cat test.txt
baz
bar

Eu gostaria de poder colocar esse comando sed dentro de um script chamado test.sh assim:

#!/bin/sh
sed "1s%.*%baz%" "test.txt" > "test.txt"

Mas, quando eu executo ./test.sh , remove todas as linhas do text.txt (o text.txt está completamente vazio)?!

Alguma idéia?

    
por Upgradingdave 14.10.2011 / 02:57

1 resposta

6

Você não pode (com segurança) redirecionar a saída de um comando para um arquivo que está sendo lido. Você está "com sorte" por ter funcionado na linha de comando. Provavelmente, em um caso sed foi capaz de ler o arquivo inteiro antes que o shell o derrotasse, e no outro caso não foi. A diferença é provavelmente devido a algum problema de buffer, mas não vale a pena descobrir isso.

Se você quiser modificar um arquivo, você deve gravar a saída em um arquivo temporário e (se tiver êxito) renomear o arquivo temporário para o nome do arquivo de entrada.

Por exemplo:

sed "1s%.*%baz%" test.txt > $$ && mv $$ test.txt

$$ é o ID do processo do shell atual; é uma maneira conveniente de obter um nome de arquivo razoavelmente exclusivo. Ou você pode usar, digamos, test.txt.$$ ou mesmo tmp se não tiver algo com esse nome.

No caso particular do comando sed , você pode usar a opção -i para modificar um arquivo - mas isso só faz com que sed crie um arquivo temporário internamente. A sintaxe, ou mesmo a existência, se a opção -i puder variar de uma implementação sed para outra; verifique sua documentação local.

    
por 14.10.2011 / 03:11

Tags