Como posso compactar um arquivo no Linux no local, sem usar espaço em disco adicional?

19

Eu tenho uma unidade de 100 GB que tem um arquivo de 95 GB. Eu preciso liberar algum espaço na unidade (e agora mesmo transferir o arquivo para fora da unidade não é uma opção). O arquivo seria compactado bem com gzip ou bz2 ou qualquer outra coisa, mas todos esses programas gravam o arquivo compactado em um arquivo separado. Eu não tenho espaço livre suficiente para isso.

Existe uma maneira de usar ferramentas de compactação padrão ou outros utilitários Unix para compactar o arquivo sem usar nenhum espaço em disco adicional (ou pelo menos uma quantidade mínima de espaço em disco adicional)? Estou imaginando algo que comprime parte do arquivo de cada vez e grava os resultados diretamente sobre o arquivo. Percebo que isso seria arriscado, pois o arquivo ficaria corrompido se a compressão fosse interrompida, mas não acho que tenho escolha.

    
por Lee 14.01.2012 / 03:49

4 respostas

13

Esta é uma prova de conceito bash one-liner, mas deve começar. Use a seu próprio risco.

truncate -s 'gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'' file
mv file file.gz

Isso funciona canalizando os dados gz para um processo dd que o escreve de volta no mesmo arquivo. Após a conclusão, o arquivo é truncado para o tamanho da saída gz.

Isso pressupõe que a última linha da saída de dd corresponde:

4307 bytes (4.3 kB) copied, 2.5855e-05 s, 167 MB/s

Onde o primeiro campo é um inteiro de bytes escritos. Este é o tamanho que o arquivo precisará ser truncado. Não tenho 100% de certeza de que o formato de saída é sempre o mesmo.

    
por 16.01.2012 / 07:36
6

Não é tanto que gzip e bzip2 sobrescrevam o original. Em vez disso, eles gravam os dados compactados no disco como um novo arquivo e, se essa operação for bem-sucedida, eles desvinculam o arquivo original descompactado.

Se você tiver RAM suficiente, poderá escrever um script para compactar temporariamente os arquivos em um sistema de arquivos tmpfs , depois remover o original no disco e substituí-lo pela versão compactada. Talvez algo assim:

# some distributions mount /dev/shm as tmpfs; replace with bzip2 if you prefer
if gzip -q9c /full/disk/somefile > /dev/shm/somefile.gz
then
    rm -f /full/disk/somefile && mv -i /dev/shm/somefile.gz /full/disk
fi

Lembre-se apenas do uso da memória, pois tmpfs é essencialmente um disco RAM. Um arquivo de saída grande pode facilmente prejudicar o sistema e causar outros problemas para você.

    
por 14.01.2012 / 06:01
3

Não há ferramenta que funcione dessa maneira, exatamente pelo motivo que você dá. Poucas pessoas estão dispostas a escrever uma ferramenta que deliberadamente implemente um comportamento de risco.

    
por 14.01.2012 / 03:58
1

Os comandos split e csplit podem ser usados para dividir o arquivo grande em partes menores e depois compactá-lo individualmente. A remontagem seria bastante demorada.

    
por 14.01.2012 / 06:48