Como posso alterar a primeira linha de um arquivo gzip grande sem descompactar tudo isso?

4

Atualmente, tenho um arquivo compactado, A.gz , que contém muitos dados tabulados, incluindo um cabeçalho na primeira linha. Eu quero criar outro arquivo, B.gz , que tem os mesmos dados que o arquivo anterior, mas com um cabeçalho diferente.

A maneira mais simples de fazer isso seria descompactar todo o A.gz , tail - tudo, exceto a primeira linha, e comprimir novamente tudo. No entanto, isso parece ineficiente, especialmente porque a concatenação de dois arquivos gzip -ed é descompactada corretamente para a concatenação das versões descompactadas.

Eu queria saber se havia uma maneira de fazer isso de forma semelhante:

zcat A.gz | head -n 1 | process_header | gzip > B.gz
cat A.gz | (remove compressed header) >> B.gz

Sem ter que descomprimir todo o A.gz .

    
por Martín Fixman 01.09.2015 / 17:07

3 respostas

1

Se você quisesse inserir outra linha no topo, seria simples.

echo some line | gzip > newfile.gz
cat newfile.gz oldfile.gz > result.gz

O gzip permite a concatenação. Se você não se importar em relatar um tamanho de arquivo descompactado errado, basta olhar para o arquivo sem descompactá-lo, ou seja. Além disso, alguns programas não podem manipular esses arquivos, WinRAR, por exemplo.

Para se aproximar do que você realmente quer, a questão é se o seu arquivo gzip é composto de blocos que funcionam inteiramente independentes um do outro e, em caso afirmativo, como encontrar o limite do bloco.

Se você sabia que queria fazer isso de antemão e criou o gzip concatenando dois arquivos gzip independentes, seria fácil resolvê-lo; no entanto, em arquivos gzip arbitrários, se isso puder ser feito, será necessário um conhecimento mais aprofundado do formato do arquivo gzip.

Eu lembro que havia um programa desse tipo para o bzip2 (mas eu esqueci o nome dele), ele criou um mapa de bloco bzip2 que permitiria acesso direto a deslocamentos específicos sem descompactar tudo o que veio antes dele.

Na linha inferior, porém, a maioria das pessoas apenas recompacta. Você provavelmente não será capaz de evitar reescrever o arquivo inteiro de qualquer forma e escrever arquivos é geralmente mais lento do que o gzip pode comprimir dados, então - se você conseguiu retirá-lo, você provavelmente pouparia alguns ciclos de CPU, mas sem tempo .

Não é uma solução para sua pergunta gzip , mas ... não use tail para se livrar da primeira linha, provavelmente é muito ineficiente em comparação a sed 1d ou o que for. Não há necessidade de contar todas as linhas de um arquivo apenas para se livrar do primeiro.

    
por 01.09.2015 / 18:10
0

Que tal

zcat A.gz | awk '{if(NR==1){print "myheader"}else{print $0}}' | gzip > B.gz

Se NR (número de registro) for 1, imprima seu próprio cabeçalho. Deixe todas as outras linhas intactas.

    
por 01.09.2015 / 17:12
0

!!! Este é apenas um pensamento !!!

Você pode tentar e executar

zcat file | head -n100 > tempfile 
vim tempfile # edit the file header
cat tempfile | gzip | dd of=B.gz conv=notrunc

isso extrairá apenas as primeiras 100 linhas dos arquivos compactados e, em seguida, irá compactá-las novamente e substituirão os mesmos blocos no arquivo B.gz e.

o problema é que essa não é uma solução real, pois você precisará garantir que os dados ANTES e PÓS consumam a mesma quantidade de bytes e, em seguida, execute o arquivo e calcule o CRC32 para o novo arquivo e grave-o no rodapé do arquivo.

Provavelmente, é melhor que você tenha a resposta steve .

    
por 01.09.2015 / 17:38