2010-10-18 9 views
10

Tengo una tarea recurrente de dividir un conjunto de archivos de registro de Apache con gzip grandes (alrededor de 1-2 GiB cada uno) en varias partes (por ejemplo, fragmentos de 500K líneas). Los archivos finales se deben volver a codificar para limitar el uso del disco.División de archivos de registro descomprimidos sin almacenar los splits sin comprimir en el disco

En Linux Yo suelo hacer:

zcat biglogfile.gz | split -l500000 

Los archivos resultantes archivos se nombrarán Xaa, xab, XAC, etc Así que hago:

gzip x* 

El efecto de este método es que como un resultado intermedio, estos enormes archivos se almacenan temporalmente en el disco. ¿Hay alguna manera de evitar este uso intermedio del disco?

¿Puedo (de una manera similar a lo que hace xargs) dividir la salida de la tubería a través de un comando (como gzip) y volver a comprimir la salida sobre la marcha? ¿O estoy mirando en la dirección incorrecta y hay una forma mucho mejor de hacerlo?

Gracias.

+0

Me gustaría implementar la funcionalidad de estilo dividido en un lenguaje de scripting, donde podría escribir las líneas directamente en archivos comprimidos. –

Respuesta

18

Puede utilizar la opción slpit --filter como se explica en el ejemplo the manual

zcat biglogfile.gz | split -l500000 --filter='gzip > $FILE.gz' 

Editar: no se dan cuenta cuando se introdujo --filter opción pero de acuerdo con los comentarios, que no está funcionando en core utils 8.4.

+1

Gracias. Creo que usar una característica en split que fue diseñada para hacer este tipo de operación es siempre mejor que el código interno. –

+2

muy bonito, pero tenga en cuenta que la división de coreutils 8.4 no tiene un 'filtro' argumnet – zach

+0

gracias @zach He actualizado la respuesta – jimkont

-1

Hay zipsplit, pero eso usa el algoritmo zip en lugar del algoritmo gzip.

3

Un script como el siguiente puede ser suficiente.

#!/usr/bin/perl 
use PerlIO::gzip; 

$filename = 'out'; 
$limit = 500000; 

$fileno = 1; 
$line = 0; 

while (<>) { 
    if (!$fh || $line >= $limit) { 
     open $fh, '>:gzip', "$filename_$fileno"; 
     $fileno++; 
     $line = 0; 
    } 
    print $fh $_; $line++; 
} 
+0

Gracias, su ejemplo rápido me ayudó mucho. Con dos correcciones menores (la primera línea debe comenzar con #!/Y después de $ fileno ++ se necesita una línea $ adicional = 0) funcionó lo suficientemente bien para mis propósitos. –

+0

Gracias. He añadido ésos al guión para la integridad. –

Cuestiones relacionadas