Por que redirecionar a saída de um arquivo para si produz um arquivo em branco?

17

Por que redirecionar a saída de um arquivo para si produz um arquivo em branco?

Em Bash, por que

less foo.txt > foo.txt

e

fold foo.txt > foo.txt

produz um foo.txt vazio? Como um acréscimo como less eggs.py >> eggs.py produz duas cópias do texto em eggs.py , pode-se esperar que uma sobregravação produza uma cópia do texto.

Note que não estou dizendo que isso seja um bug, é mais provável que seja um sinal de algo profundo sobre o Unix.

    
por seewalker 19.05.2013 / 07:02

2 respostas

18

Quando você usa > , o arquivo é aberto no modo de truncamento para que seu conteúdo seja removido antes que o comando tente lê-lo.

Quando você usa >> , o arquivo é aberto no modo de acréscimo para que os dados existentes sejam preservados. No entanto, ainda é bastante arriscado usar o mesmo arquivo como entrada e saída nesse caso. Se o arquivo for grande o suficiente para não caber no tamanho do buffer de entrada de leitura, seu tamanho poderá crescer indefinidamente até que o sistema de arquivos esteja cheio (ou sua cota de disco seja atingida).

Se você quiser usar um arquivo como entrada e saída com um comando que não suporta modificação no local, use algumas soluções alternativas:

  • Use um arquivo intermediário e sobrescreva o original quando terminar e somente se nenhum erro ocorrer durante a execução do utilitário (essa é a maneira mais segura e mais comum).

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
    
  • Evite o arquivo intermediário às custas de uma possível perda de dados parcial ou completa caso ocorra um erro ou interrupção. Neste exemplo, o conteúdo de foo.txt é passado como entrada para uma subshell (dentro dos parênteses) antes o arquivo é excluído. O inode anterior permanece ativo, pois o subshell o mantém aberto durante a leitura de dados. O arquivo escrito pelo utilitário interno (aqui fold ) enquanto tem o mesmo nome ( foo.txt ) aponta para um inode diferente porque a entrada do diretório antigo foi removida, portanto, tecnicamente, existem dois "arquivos" diferentes com o mesmo nome durante o processo. Quando a subshell termina, o inode antigo é liberado e seus dados são perdidos. Cuidado para ter certeza de que você tem espaço suficiente para armazenar temporariamente o arquivo antigo e o novo ao mesmo tempo, caso contrário, você perderá dados.

    (rm foo.txt; fold > foo.txt) < foo.txt
    
por 19.05.2013 / 08:51
7

O arquivo é aberto para gravação pelo shell antes que o aplicativo tenha a chance de lê-lo. Abrir o arquivo para escrita trunca.

    
por 19.05.2013 / 07:22