Tenho certeza de que alguém teve a necessidade abaixo. Qual é uma maneira rápida de dividir um arquivo .gz enorme por linha? O arquivo de texto subjacente possui 120 milhões de linhas. Não tenho espaço em disco suficiente para compactar o arquivo inteiro de uma vez, então gostaria de saber se alguém conhece um script ou ferramenta bash/perl que possa dividir o arquivo (o .gz ou o .txt interno) em 3 arquivos de linha de 40 minutos . ou seja, chamando-o como:
bash splitter.sh hugefile.txt.gz 4000000 1
would get lines 1 to 40 mn
bash splitter.sh hugefile.txt.gz 4000000 2
would get lines 40mn to 80 mn
bash splitter.sh hugefile.txt.gz 4000000 3
would get lines 80mn to 120 mn
Talvez uma série dessas seja uma solução ou o gunzip -c exigiria espaço suficiente para que o arquivo inteiro fosse descompactado (ou seja, o problema original): gunzip -c enormefile.txt.gz | cabeça 4000000
Nota: não consigo disco extra.
Obrigado!
Responder1
A melhor forma de fazer isso depende do que você deseja:
- Você deseja extrair uma única parte do arquivo grande?
- Ou você deseja criar todas as peças de uma só vez?
Se você quiser umúnica parte do arquivo, sua ideia de usar gunzip
e head
está certa. Você pode usar:
gunzip -c hugefile.txt.gz | head -n 4000000
Isso geraria as primeiras 4.000.000 linhas na saída padrão - você provavelmente deseja anexar outro canal para realmente fazer algo com os dados.
Para obter as outras partes, você usaria uma combinação de head
e tail
, como:
gunzip -c hugefile.txt.gz | head -n 8000000 |tail -n 4000000
para obter o segundo bloco.
Talvez uma série dessas seja uma solução ou o gunzip -c exigiria espaço suficiente para que o arquivo inteiro fosse descompactado
Não, gunzip -c
não requer espaço em disco - ele faz tudo na memória e depois transmite para stdout.
Se você quiser criartodas as peças de uma só vez, é mais eficiente criá-los todos com um único comando, pois assim o arquivo de entrada só é lido uma vez. Uma boa solução é usar split
; veja a resposta de Jim Mcnamara para obter detalhes.
Responder2
pipe para dividir use gunzip -c ou zcat para abrir o arquivo
gunzip -c bigfile.gz | split -l 400000
Adicione especificações de saída ao comando split.
Responder3
Como você está trabalhando em um fluxo (não rebobinável), você desejará usar a forma '+N' de cauda para obter linhas começando da linha N em diante.
zcat hugefile.txt.gz | head -n 40000000
zcat hugefile.txt.gz | tail -n +40000001 | head -n 40000000
zcat hugefile.txt.gz | tail -n +80000001 | head -n 40000000
Responder4
Divida diretamente o arquivo .gz em arquivos .gz:
zcat bigfile.gz | split -l 400000 --filter='gzip > $FILE.gz'
Acho que era isso que o OP queria, porque ele não tem muito espaço.