¿Cómo puedo acortar un archivo desde la línea de comando?

9

Tengo un archivo xml de 150 GB que me gustaría acortar (es decir, truncar) a aproximadamente 1 GB: ¿puedo usar un comando simple (bash o similar) o debo seguir la ruta programática (editándolo en vi o emacs es una pesadilla incluso en grandes sistemas de hierro)?

(No estoy particularmente preocupado por la pérdida de información, quiero un archivo más corto para poder probar una pieza de software al respecto y no esperar muchas horas por la respuesta, un archivo más corto me permitirá hacerlo).

adrianmcmenamin
fuente
1
¿Quiere decir que desea truncar el archivo o desea eliminar información de todo el archivo?
AFH
1
Encontré esto en SO; stackoverflow.com/a/15934078/2800918 .
CAB
2
Dado que este es un archivo XML, que supongo que contiene una secuencia con una gran cantidad de elementos, también podría usar un lenguaje de transformación XML como XQuery para filtrar una cierta cantidad de estos elementos, lo que tendría la ventaja de generar XML válido ( Ejemplo )
Aaron
44
¿El archivo aún necesita ser XML válido cuando haya terminado?
Joe
1
no, lo acabo de arreglar para que así fuera
adrianmcmenamin

Respuestas:

15

Suponiendo que desea truncar y extraer el primer 1 GB del archivo de 150 GB:

Con head:

head -c 1G infile > outfile

Tenga en cuenta que el Gsufijo puede reemplazarse GBpara alinearse con 1000 en lugar de 1024.

O con dd:

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

O como en Wumpus Q. La respuesta de Wumbley, ddpuede truncarse en su lugar.

multithr3at3d
fuente
55
Es probable que eso no resulte en un archivo XML legible cuando haya terminado.
Joe
3
@ Joe - OP no solicitó un archivo legible (ni dijeron que pudiera ser ilegible). Dijeron que no les importaba la pérdida de información. Esperaría una nueva pregunta de OP sobre cómo solucionar dicho archivo.
KevinDTimm
3
Sé suficiente xml para arreglarlo, ¡escribí el DTD para el formato!
adrianmcmenamin
37

Para truncar un archivo a 1 gigabyte, use el truncatecomando:

truncate -s 1G file.xml

El resultado del truncamiento probablemente no será un archivo XML válido, pero supongo que lo comprende.

La documentación para la versión GNU de truncateestá aquí y la documentación para la versión BSD está aquí

John1024
fuente
14

Siempre que sea posible, usaría el truncatecomando como en la respuesta de John1024. Sin embargo, no es un comando estándar de Unix, por lo que es posible que algún día no puedas usarlo. En ese caso, también ddpuede hacer un truncamiento en el lugar.

ddEl comportamiento predeterminado es truncar el archivo de salida en el punto donde finaliza la copia, por lo que solo debe darle un archivo de entrada de longitud 0 y decirle que comience a escribir en el punto de truncamiento deseado:

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

(Esto no es lo mismo que copiar y truncar dden la respuesta de multithr3at3d).

Tenga en cuenta que usé 1048576 y 1024 porque 1048576 * 1024 es el tamaño deseado. Evité bs = 1m porque se trata de una respuesta "portabilidad", y clásicos ddsólo sabe sufijos k, by w.


fuente
2
Para la solución general, probablemente debería tener en cuenta que el bsnúmero multiplicado por el seeknúmero es el número de bytes que se deben mantener. Cualquier dos números que satisfagan esa restricción deberían funcionar; por ejemplo, bs=1073741824 seek=1o bs=1 seek=1073741824. O, dado que el valor bspredeterminado es 512, seek=2097152solo también debería funcionar. Y puede utilizar la notación como 1M, 1K, 1Gy 2M.
G-Man dice 'reinstalar a Monica' el
1

No estoy completamente seguro de lo que estás preguntando. ¿Solo quiere deshacerse de los otros 149 GB o está tratando de comprimir 150 GB en 1 GB? Independientemente, este puede ser un método útil para lograr esto.

El splitcomando puede dividir cualquier archivo en varias partes. Ver hombre dividido . Puede especificar el tamaño de los fragmentos de archivo en los que desea dividirlo con la -bopción. Por ejemplo:

$ split -b 1GB myfile.xml

Sin ninguna otra opción, esto debería crear varios archivos en el directorio actual comenzando con la letra x. Si desea ajustar los nombres de los archivos divididos, consulte la página del manual.

Para volver a ensamblar el archivo simplemente use cat * > re-assembled.xml.

Ejemplo:

[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
fuente
0

Al final solo solía sedextraer un número arbitrario de líneas:

sed -n 1,1000000p infile.xml>outfile.xml
adrianmcmenamin
fuente
1
Dejando a un lado si esto responde a la pregunta o no, esto escaneará todo el archivo, creo, por lo que es mucho más eficiente de usar sed 1000000q(y un poco más compacto, visualmente hablando).
Capa B