2010-10-18 6 views
10

J'ai une tâche récurrente consistant à diviser un ensemble de grands fichiers journaux Apache gzippés en plusieurs parties (disons des blocs de 500 000 lignes). Les fichiers finaux doivent être gzippés à nouveau pour limiter l'utilisation du disque.Séparation des fichiers journaux gzippés sans stocker les partitions non compressées sur le disque

Sur Linux je normalement faire:

zcat biglogfile.gz | split -l500000 

Les fichiers fichiers seront nommés Xaa, xab, XAC, etc Je fais:

gzip x* 

L'effet de cette méthode est cela comme résultat intermédiaire ces énormes fichiers sont temporairement stockés sur le disque. Est-il possible d'éviter cette utilisation de disque intermédiaire? Puis-je (d'une manière similaire à xargs) diviser la sortie via une commande (comme gzip) et recomprimer la sortie à la volée? Ou est-ce que je regarde dans la mauvaise direction et y a-t-il une bien meilleure façon de faire cela?

Merci.

+0

Je voudrais examiner la mise en œuvre de la fonctionnalité de style fractionné dans un langage de script, où vous pouvez écrire les lignes directement dans des fichiers gzippés. –

Répondre

18

Vous pouvez utiliser l'option de --filter slpit comme expliqué dans the manual par exemple

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

Edit: pas au courant lorsque l'option --filter a été introduite, mais selon les commentaires, il ne fonctionne pas dans core utils 8.4.

+1

Merci. Je pense que l'utilisation d'une fonctionnalité dans la division qui a été conçue pour faire ce genre d'opération est toujours mieux que le code du homegrown. –

+2

très bien mais notez que la division de coreutils 8.4 n'a pas de 'filtre' argumnet – zach

+0

merci @zach j'ai mis à jour la réponse – jimkont

-1

zipsplit est utilisé, mais il utilise l'algorithme zip plutôt que l'algorithme gzip.

3

Un script du type suivant peut suffire.

#!/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

Merci, votre exemple rapide m'a beaucoup aidé. Avec deux corrections mineures (la première ligne doit commencer par #!/Et après $ fileno ++ une ligne $ additionnelle = 0 est nécessaire) cela a fonctionné assez bien pour mes besoins. –

+0

Merci. J'ai ajouté ceux-ci au script pour l'exhaustivité. –

Questions connexes