A experiência mostra que isso não funciona .
Eu criei um arquivo de 2 megabytes a partir de /dev/urandom
e, em seguida, testei o comando acima nele. Aqui estão os resultados:
% ls -l
total 41008
-rw-r--r-- 1 kst kst 20971520 2012-01-18 03:47 file
-rw-r--r-- 1 kst kst 20971520 2012-01-18 02:48 orig
% gzip -c file | dd of=file
0+1 records in
0+1 records out
25 bytes (25 B) copied, 0.000118005 s, 212 kB/s
% ls -l
total 20508
-rw-r--r-- 1 kst kst 25 2012-01-18 03:47 file
-rw-r--r-- 1 kst kst 20971520 2012-01-18 02:48 orig
$
Obviamente, um arquivo aleatório de 2 megabytes não é compactado em 25 bytes e, na verdade, a execução de gunzip
no arquivo compactado gera um arquivo vazio.
Eu obtive resultados semelhantes para um arquivo aleatório muito menor (100 bytes).
Então, o que aconteceu?
Nesse caso, o comando dd
truncou file
para zero bytes antes de começar a gravar nele; gzip
começou a ler o arquivo recém-vazio e produziu 25 bytes de saída, que dd
anexou ao file
vazio. (Um arquivo vazio "comprime" para um tamanho diferente de zero; é teoricamente impossível para qualquer compressor tornar a entrada all menor).
Outros resultados podem ser possíveis, dependendo do tempo dos processos gzip
, dd
e shell, todos em execução paralelamente.
Há uma condição de corrida porque um processo, gzip
, lê a partir de file
, enquanto outro processo paralelo, o shell, grava nele.
Deve ser possível implementar um compressor de arquivo no local que leia e grave no mesmo arquivo, usando qualquer buffer interno necessário para evitar a perda de dados. Mas eu nunca ouvi falar de alguém realmente implementando isso, provavelmente porque geralmente não é necessário e porque se o compressor falhar no meio do caminho, o arquivo será permanentemente corrompido.