Je suis sûr que quelqu'un a eu le besoin ci-dessous, quel est un moyen rapide de diviser un énorme fichier .gz par ligne? Le fichier texte sous-jacent comporte 120 millions de lignes. Je n'ai pas assez d'espace disque pour compresser le fichier en entier à la fois, donc je me demandais si quelqu'un connaissait un script ou un outil bash / perl qui pourrait diviser le fichier (soit le .gz ou le .txt interne) en 3 fichiers de ligne de 40mn . c'est-à-dire l'appeler comme:
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
Peut-être qu'une série de ces solutions est une solution ou le gunzip -c nécessiterait-il suffisamment d'espace pour que le fichier entier soit décompressé (c'est-à-dire le problème d'origine): gunzip -c énormefichier.txt.gz | tête 4000000
Remarque: je ne peux pas obtenir de disque supplémentaire.
Merci!
Réponses:
La meilleure façon de procéder dépend de ce que vous voulez:
Si vous voulez une seule partie du fichier , votre idée d'utiliser
gunzip
ethead
est juste. Vous pouvez utiliser:Cela produirait les 400 000 premières lignes sur la sortie standard - vous voudrez probablement ajouter un autre canal pour réellement faire quelque chose avec les données.
Pour obtenir les autres parties, vous utiliseriez une combinaison de
head
ettail
, comme:pour obtenir le deuxième bloc.
Non, le
gunzip -c
ne nécessite aucun espace disque - il fait tout en mémoire, puis le diffuse sur stdout.Si vous souhaitez créer toutes les pièces en une seule fois , il est plus efficace de les créer toutes avec une seule commande, car le fichier d'entrée n'est lu qu'une seule fois. Une bonne solution consiste à utiliser
split
; voir la réponse de Jim Mcnamara pour plus de détails.la source
gzip
ne connaît pas la limite (qui provient d'un processus différent). Sihead
est utilisé, sehead
terminera lorsqu'il en aura reçu suffisamment, et cela se propagera versgzip
(via SIGPIPE, voir Wikipedia). Cartail
ce n'est pas possible, alors oui,gzip
tout décompressera.pipe à diviser utilisez gunzip -c ou zcat pour ouvrir le fichier
Ajoutez des spécifications de sortie à la commande de division.
la source
Comme vous travaillez sur un flux (non rembobinable), vous souhaiterez utiliser la forme de queue '+ N' pour obtenir des lignes à partir de la ligne N.
la source
J'envisagerais d'utiliser split .
la source
Divisez directement le fichier .gz en fichiers .gz:
Je pense que c'est ce que voulait OP, car il n'a pas beaucoup d'espace.
la source
Voici un script python pour ouvrir un ensemble de fichiers globalisés à partir d'un répertoire, les compresser si nécessaire et les parcourir ligne par ligne. Il utilise uniquement l'espace nécessaire en mémoire pour contenir les noms de fichiers et la ligne actuelle, plus un peu de surcharge.
La commande print line enverra chaque ligne vers std out, vous pouvez donc rediriger vers un fichier. Alternativement, si vous nous faites savoir ce que vous voulez faire avec les lignes, je peux l'ajouter au script python et vous n'aurez pas besoin de laisser des morceaux du fichier autour.
la source
Voici un programme perl qui peut être utilisé pour lire stdin et diviser les lignes, en redirigeant chaque groupe vers une commande distincte qui peut utiliser une variable shell $ SPLIT pour l'acheminer vers une destination différente. Pour votre cas, il serait invoqué avec
zcat hugefile.txt.gz | perl xsplit.pl 40000000 'cat > tmp$SPLIT.txt; do_something tmp$SPLIT.txt; rm tmp$SPLIT.txt'
Désolé, le traitement en ligne de commande est un peu compliqué, mais vous avez l'idée.
la source