Por que sed -i não funciona com fd

3

Eu tenho este arquivo e fd: exec 88<>abc

Por que

$ sed -i "s/cd/II/g" /proc/$$/fd/88
sed: couldn't open temporary file /proc/26194/fd/sedS1D1FT: No such file or directory

mas este trabalho:

$ cat /proc/self/fd/88 | sed  "s/cd/II/g" 
abIIefg

E então isso não funciona:

$ (cat /proc/self/fd/88 | sed  "s/cd/II/g")  > /proc/self/fd/88

isto faz com que / proc / self / fd / 88 fique vazio

    
por Bob Johnson 07.11.2018 / 09:56

2 respostas

5

sed -i na verdade não edita o arquivo "in-place", nunca; ele funciona redirecionando sua saída para um arquivo temporário e renomeando / movendo o arquivo temporário para o original.

Isso garante que o arquivo original não seja perdido no caso de algo dar errado no meio do caminho.

Para piorar, sed (como vim ) tenta criar o arquivo temporário no mesmo diretório que o original.

O sistema de arquivos /proc é sintético , você não pode simplesmente criar ou mover arquivos dentro dele; é por isso que você está recebendo esse erro. Mas mesmo que sed estivesse criando o arquivo temporário em /tmp , a última operação (a renomeação do arquivo temporário para o original) ainda falharia.

Você pode tentar fazer o que o sed -i faz de uma maneira circular:

$ ised(){ for a; do :; done; t='mktemp' && sed "$@" > "$t" && cat "$t" > "$a" && rm "$t"; }
$ ised s/cd/II/g /proc/$$/fd/88

O nome do arquivo sempre deve ser o último argumento para ised .

Isso quebra a garantia de consistência de sed -i ; a operação cat in > out , ao contrário de mv in out , não é atômica; se parado no meio, o arquivo out será truncado.

    
por 08.11.2018 / 05:58
0

Supondo que o arquivo real ainda exista, isso pode funcionar melhor (mas use com cuidado, pois isso modificaria um arquivo real):

sed -i s/cd/II/g "$(realpath "/proc/$$/fd/88")"

Como mosvy notas , isso não funcionará se o resultado de realpath /proc/$$/fd/88 já tiver sido excluído. Exemplo:

exec 7>/tmp/junk; echo yes >&7; rm /tmp/junk; 
cat /proc/$$/fd/7; cat "$(realpath "/proc/$$/fd/7")"

Saída (mesmo que / tmp / junk não exista), 1a linha para STDOUT , segunda linha para STDERR :

yes
cat: '/tmp/junk (deleted)': No such file or directory
    
por 08.11.2018 / 05:26