Como encurtar um arquivo na linha de comando?

9

Eu tenho um arquivo xml de 150GB que gostaria de encurtar (ou seja, truncar) para cerca de 1GB - existe um comando simples (bash ou similar) que posso usar ou tenho que seguir a rota programática (editando-o no vi ou no emacs é um pesadelo mesmo em grandes sistemas de ferro)?

(Não estou particularmente preocupado com a perda de informações, quero um arquivo mais curto para poder testar um pedaço de software e não esperar muitas horas pela resposta; um arquivo mais curto me permitirá fazer isso.)

adrianmcmenamin
fonte
1
Você quer truncar o arquivo ou remover informações de todo o arquivo?
AFH
1
Encontrei isso no SO; stackoverflow.com/a/15934078/2800918 .
CAB
2
Como esse é um arquivo XML, que suponho que contém uma sequência com um grande número de elementos, você também pode usar uma linguagem de transformação XML como o XQuery para filtrar um certo número desses elementos, o que teria a vantagem de gerar XML válido ( Exemplo )
Aaron
4
O arquivo ainda precisa ser XML válido quando concluído?
Joe
1
não, eu apenas o
remendei

Respostas:

15

Supondo que você deseja truncar e extrair os primeiros 1 GB do arquivo de 150 GB:

Com head:

head -c 1G infile > outfile

Observe que o Gsufixo pode ser substituído por GBpara alinhar a 1000 em vez de 1024.

Ou com dd:

dd if=infile of=outfile bs=1M count=1024

Ou, como na resposta de Wumpus Q. Wumbley, ddpode truncar no lugar.

multithr3at3d
fonte
5
Isso provavelmente não resultará em um arquivo XML legível quando concluído.
Joe Joe
3
@ Joe - OP não solicitou um arquivo legível (nem disseram que poderia ser ilegível). Eles disseram que não se preocupavam com a perda de informações. Eu esperaria uma nova pergunta do OP sobre como corrigir esse arquivo.
precisa saber é o seguinte
3
Eu sei xml suficiente para corrigi-lo, eu escrevi o DTD para o formato!
Adrianmcmenamin
37

Para truncar um arquivo para 1 gigabyte, use o truncatecomando:

truncate -s 1G file.xml

O resultado do truncamento provavelmente não será um arquivo XML válido, mas entendo que você entende isso.

A documentação para a versão GNU de truncateestá aqui e a documentação para a versão BSD está aqui

John1024
fonte
14

Sempre que possível, eu usaria o truncatecomando como na resposta de John1024. No entanto, não é um comando unix padrão; portanto, um dia você poderá ser incapaz de usá-lo. Nesse caso, ddtambém é possível fazer um truncamento no local.

ddO comportamento padrão do usuário é truncar o arquivo de saída no ponto em que a cópia termina, portanto, basta fornecer um arquivo de entrada de tamanho 0 e solicitar que comece a escrever no ponto de truncamento desejado:

dd if=/dev/null of=filename bs=1048576 seek=1024

(Isso não é o mesmo que copiar e truncar ddna resposta do multithr3at3d.)

Observe que eu usei 1048576 e 1024 porque 1048576 * 1024 é o tamanho desejado. Evitei bs = 1m porque esta é uma resposta "portabilidade", e clássico ddsó conhece sufixos k, be w.


fonte
2
Para a solução geral, você provavelmente deve observar que o bsnúmero multiplicado pelo seeknúmero é o número de bytes a serem mantidos. Quaisquer dois números que satisfaçam essa restrição devem funcionar; por exemplo, bs=1073741824 seek=1ou bs=1 seek=1073741824. Ou, como o bspadrão é 512, por seek=2097152si só também deve funcionar. E você pode usar a notação como 1M, 1K, 1Ge 2M.
G-Man
1

Não tenho muita certeza do que você está perguntando. Você só quer se livrar dos outros 149 GB ou está tentando compactar 150 GB em 1 GB? Independentemente disso, esse pode ser um método útil para fazer isso.

O splitcomando pode dividir qualquer arquivo em várias partes. Veja o homem se separar . Você pode especificar o tamanho dos blocos de arquivos nos quais deseja dividi-los com a -bopção Por exemplo:

$ split -b 1GB myfile.xml

Sem outras opções, isso deve criar vários arquivos no diretório atual, começando com a letra x. Se você deseja ajustar os nomes dos arquivos divididos, consulte a página do manual.

Para remontar o arquivo, basta usar cat * > re-assembled.xml.

Exemplo:

[kent_x86.py@c7 split-test]$ ls -l opendocman*
-rw-rw-r--.  1 kent_x86.py kent_x86.py 2082602 Mar 31  2017 opendocman-1.3.5.tar.gz

[kent_x86.py@c7 split-test]$ split -b 100K opendocman-1.3.5.tar.gz 
[kent_x86.py@c7 split-test]$ ls
opendocman-1.3.5.tar.gz  xaa  xab  xac  xad  xae  xaf  xag  xah  xai  xaj  xak  xal  xam  xan  xao  xap  xaq  xar  xas  xat  xau
[kent_x86.py@c7 split-test]$ ll
total 4072
-rw-rw-r--. 1 kent_x86.py kent_x86.py 2082602 Jan  5 11:06 opendocman-1.3.5.tar.gz
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaa
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xab
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xac
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xad
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xae
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaf
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xag
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xah
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xai
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaj
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xak
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xal
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xam
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xan
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xao
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xap
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xaq
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xar
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xas
-rw-rw-r--. 1 kent_x86.py kent_x86.py  102400 Jan  5 11:06 xat
-rw-rw-r--. 1 kent_x86.py kent_x86.py   34602 Jan  5 11:06 xau
[kent_x86.py@c7 split-test]$ cat xa* > opendoc-reassembled.tar.gz
[kent_x86.py@c7 split-test]$ ls -l opendoc-reassembled*
-rw-rw-r--. 1 kent_x86.py kent_x86.py 2082602 Jan  5 11:07 opendoc-reassembled.tar.gz
Kentgrav
fonte
0

No final, apenas usei sedpara extrair um número arbitrário de linhas:

sed -n 1,1000000p infile.xml>outfile.xml
adrianmcmenamin
fonte
1
Deixando de lado se isso responde à pergunta ou não, isso examinará o arquivo inteiro, acredito, por isso é muito mais eficiente de usar sed 1000000q(e um pouco mais compacto, visualmente falando).
Camada B