O redirecionamento é '' equivalente a '' quando o arquivo de destino ainda não existe?

79

Considere um shell como Bash ou sh. A diferença básica entre > e >> se manifesta em um caso em que o arquivo de destino existe:

  • > trunca o arquivo para o tamanho zero e, em seguida, escreve;
  • >> não trunca, escreve (acrescenta) ao final do arquivo.

Se o arquivo não existir, ele será criado com tamanho zero; então escrito para. Isso é verdade para ambos os operadores. Pode parecer que os operadores são equivalentes quando o arquivo de destino ainda não existe.

Eles são realmente?

    
por Kamil Maciorowski 23.07.2018 / 10:42

1 resposta

107

tl; dr

Não. >> é essencialmente "sempre buscar fim do arquivo", enquanto > mantém um ponteiro para o último local escrito.

Resposta completa

(Nota: todos os meus testes feitos no Debian GNU / Linux 9).

Outra diferença

Não, eles não são equivalentes. Há outra diferença. Ele pode se manifestar independentemente de o arquivo de destino existir antes ou não.

Para observá-lo, execute um processo que gera dados e redirecione para um arquivo com > ou >> (por exemplo, pv -L 10k /dev/urandom > blob ). Deixe que ele seja executado e mude o tamanho do arquivo (por exemplo, com truncate ). Você verá que > mantém seu deslocamento (crescente) enquanto >> sempre é anexado ao final.

  • Se você truncar o arquivo para um tamanho menor (pode ser o tamanho zero)
    • > não se importará, ele escreverá no deslocamento desejado como se nada tivesse acontecido; logo depois que o truncamento do deslocamento estiver além do final do arquivo, isso fará com que o arquivo recupere seu tamanho antigo e cresça mais, os dados ausentes serão preenchidos com zeros (de maneira esparsa, se possível);
    • >> será anexado à nova extremidade, o arquivo crescerá a partir do tamanho truncado.
  • Se você ampliar o arquivo
    • > não se importará, ele escreverá no deslocamento desejado como se nada tivesse acontecido; logo após alterar o tamanho, o deslocamento estará em algum lugar dentro do arquivo, isso fará com que o arquivo pare de crescer por um tempo, até que o deslocamento atinja o novo fim, então o arquivo crescerá normalmente;
    • >> será anexado à nova extremidade, o arquivo crescerá a partir do tamanho ampliado.

Outro exemplo é acrescentar (com um >> separado) algo extra quando o processo de geração de dados está sendo executado e gravado no arquivo. Isso é semelhante a ampliar o arquivo.

  • O processo de geração com > escreve no deslocamento desejado e sobrescreve os dados extras eventualmente.
  • O processo de geração com >> irá ignorar os novos dados e anexá-los (condição de corrida pode ocorrer, os dois fluxos podem ficar entrelaçados, e ainda nenhum dado deve ser sobrescrito).

Exemplo

Isso importa na prática? Há esta pergunta :

I'm running a process which produces a lot of output on stdout. Sending it all to a file [...] Can I use some kind of log rotation program?

Esta resposta diz que a solução é logrotate com copytruncate opção que age assim:

Truncate the original log file in place after creating a copy, instead of moving the old log file and optionally creating a new one.

De acordo com o que escrevi acima, redirecionar com > tornará o log truncado grande em pouco tempo. Sparseness irá salvar o dia, sem espaço em disco significativo deve ser desperdiçado. No entanto, cada log consecutivo terá cada vez mais zeros iniciais desnecessários.

Mas se logrotate criar cópias sem preservar a dispersão, esses zeros à esquerda precisarão de mais e mais espaço em disco toda vez que uma cópia for feita. Eu não investiguei o comportamento da ferramenta, pode ser inteligente o suficiente com dispersão ou compressão na hora (se a compactação estiver ativada). Ainda assim, os zeros só podem causar problemas ou ser neutros na melhor das hipóteses; nada de bom neles.

Nesse caso, usar >> em vez de > é significativamente melhor, mesmo que o arquivo de destino esteja prestes a ser criado ainda.

Desempenho

Como podemos ver, os dois operadores agem de maneira diferente, não apenas quando começam, mas também depois. Isso pode causar uma diferença de desempenho (sutil?). Por enquanto, não tenho resultados de teste significativos para apoiar ou refutar isso, mas acho que você não deve assumir automaticamente que seu desempenho é o mesmo em geral.

    
por 23.07.2018 / 10:42