Gzip-Dateien effizient in bzip2 konvertieren

10

Ich habe eine Reihe von gzip-Dateien, die ich ab und zu in bzip2 konvertieren muss. Derzeit verwende ich ein Shell-Skript, das einfach jede Datei "gunzip" und dann "bzip2" verwendet. Obwohl dies funktioniert, dauert es eine Menge Zeit , um vollständig.

Ist es möglich, diesen Prozess effizienter zu gestalten? Ich bin bereit, einen Tauchgang zu machen und bei Bedarf die Quellcodes von gunzip und bzip2 zu untersuchen, aber ich möchte nur sicher sein, dass sich das auszahlt. Gibt es Hoffnung, die Effizienz des Prozesses zu verbessern?

Sundar - Monica wieder einsetzen
quelle

Antworten:

1

Diese Frage wurde vor langer Zeit gestellt, als pbzip2 entweder nicht verfügbar war oder nicht von stdin komprimiert werden konnte. Sie können jetzt jedoch sowohl das Dekomprimieren als auch das Komprimieren von Schritten mit parallel und pbzip2 (anstelle von bzip2 ) parallelisieren :

ls *.gz | parallel "gunzip -c {} | pbzip2 -c > {.}.bz2"

Das ist deutlich schneller als mit bzip2 .

fliegender Finger
quelle
Hallo, ich habe die akzeptierte Antwort auf diese geändert, da dies die beste Option für Leute ist, die heute über die Frage stolpern. Danke für die pbzip2Erwähnung. Falls der Link für niemanden geladen wird, finden Sie hier die Projektseite und die Manpage .
Sundar - Reinstate Monica
15

Anstatt gunzip in einem Schritt und bzip2 in einem anderen, frage ich mich, ob es vielleicht effizienter wäre, Pipes zu verwenden. Etwas wiegunzip --to-stdout foo.gz | bzip2 > foo.bz2

Ich denke mit zwei oder mehr CPUs wäre dies definitiv schneller. Aber vielleicht sogar mit nur einem Kern. Ich gebe schändlicherweise zu, dies nicht ausprobiert zu haben.

ChrisInEdmonton
quelle
2
+1 für Rohrleitungen, Festplatten-E / A ist etwas, das Sie vermeiden möchten. Was die Komprimierung betrifft, ist bzip2 keine Parallele, es sei denn, ich irre mich. Sie müssten so etwas wie pbzip2 verwenden, um in parallell zu komprimieren: compress.ca/pbzip2
gustafc
... und leider scheint es kein paralleles gzip-Dekomprimierungsprogramm zu geben.
Gustafc
@gustafc: Danke für den Link zu pbzip2, das war sehr hilfreich ... @OP: Ich scheute mich vor Piping-Bcos, ich möchte in der Lage sein, mit beschädigten GZ-Dateien usw. umzugehen, ohne sie in der Pipe zu verlieren ...
Sundar - Reinstate Monica
4
@gustafc: Auch wenn bzip2und gzipnicht parallel arbeiten intern durch ein Rohr verwenden , können Sie sie parallel arbeiten, weil ein Rohr implizit zwei Prozesse gestartet, die wird parallel laufen. Zumindest Dekomprimierung und Komprimierung werden also parallel ausgeführt.
Sleske
1
@sleske, obwohl Sie theoretisch Recht haben, stellt bzip2die CPU-Auslastung gunzipdiejenige in den Schatten, sodass in der Praxis die Parallelität, die Sie hier erhalten, minimal ist. Es ist trotzdem schön, keine Festplatten-E / A ausführen zu müssen!
Johan Walles
6

GNU parallel ( http://www.gnu.org/software/parallel ) kann eine Option sein, wenn Sie mehrere Kerne (oder sogar mehrere Computer) haben:

ls *.gz | parallel "gunzip -c {} | bzip2 > {.}.bz2"

Lesen Sie das Tutorial / die Manpage für Details und Optionen.

Aufsicht
quelle
3

Was Sie gerade tun, ist Ihre beste Wahl. Es ist kein Konvertierungstool verfügbar, und der Versuch, eine bereits komprimierte Datei zu bzip2, ist keine Option, da dies häufig unerwünschte Auswirkungen hat. Da der Algorithmus unterschiedlich ist, würde das Konvertieren das Abrufen der Originaldaten unabhängig davon beinhalten. Es sei denn natürlich, GZIP war ein Schritt im bzip2-Prozess, in dem dies leider nicht der Fall ist.

John T.
quelle
Haben die Algorithmen keine überlappenden Schritte, so dass ich einen Schritt bei der gzip-Dekomprimierung und den gleichen auch bei der bzip-Komprimierung überspringen könnte?
Sundar - Reinstate Monica
2
@ Sundar würde ich nicht denken. gzipverwendet Leimpel-Ziv 77, während bzip2Burrows-Wheeler verwendet wird. Ich fürchte, verschiedene Algorithmen.
new123456
2

Gelegentlich muss ich dasselbe mit Protokolldateien tun. Ich beginne mit den kleinsten * .gz-Dateien zuerst ( ls -rS), gunzip und dann und bzip2 sie einzeln. Ich weiß nicht, ob es möglich ist, die gunzip-Ausgabe direkt auf die bzip2-Eingabe zu lenken. Der Befehl bzip2 ist beim Komprimieren so viel langsamer als der Befehl gunzip beim Dekomprimieren, dass er möglicherweise den Speicher belegt und Speicherplatz auf dem Host austauscht.

Verbesserungen oder Vorschläge sind willkommen. Hier ist mein Einzeiler:

for i in $(ls -rS *.gz | sed 's/\.gz//'); do gunzip ${i}.gz; bzip2 -9 ${i}; done
Mike L Swartz
quelle
Vielen Dank für die Eingabe, der Punkt über den Geschwindigkeitsunterschied zwischen den beiden Prozessen und seine Auswirkungen ist wichtig.
Sundar - Monica
1

Wenn Sie mehr als ein paar haben, lesen Sie den LJ-Artikel mit einem schönen Shell-Skript.

http://linuxgazette.net/123/bechtel.html

7zip erhält eine bessere Komprimierung und ist multithreaded.

Ronald Pottol
quelle
1

Musste das erst vor ein paar Minuten machen:

find . -name "*.gz" | perl -pi -e 's/\.gz$//g;' | xargs -n1 ./rezip

Wo rezipwürde definiert werden als:

#!/bin/bash
gunzip -v $1.gz && bzip2 -9v $1

Optional können Sie es auch mithilfe einer -POption mit Multithreading xargserstellen, aber seien Sie vorsichtig mit dieser Option . (Fangen Sie niedrig an!)

Brendan Byrd
quelle