Efektywna konwersja plików gzip do bzip2


10

Mam kilka plików gzip, które muszę od czasu do czasu konwertować na bzip2. Obecnie używam skryptu powłoki, który po prostu „gunzip's każdy plik, a następnie” bzip2 to. Chociaż to działa, to zajmuje dużo czasu.

Czy można uczynić ten proces bardziej wydajnym? Jestem gotów rzucić okiem i zajrzeć do kodów źródłowych gunzip i bzip2, jeśli to konieczne, ale chcę mieć pewność co do wypłaty. Czy jest jakaś nadzieja na poprawę wydajności procesu?

Odpowiedzi:


1

To pytanie zostało zadane dawno temu, gdy pbzip2 albo nie był dostępny, albo nie był w stanie kompresować ze standardowego wejścia, ale teraz możesz równolegle wykonywać kroki dekompresujące i kompresujące za pomocą programów równoległych i pbzip2 (zamiast bzip2 ):

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

co jest znacznie szybsze niż użycie bzip2 .


Cześć, Zmieniłem zaakceptowaną odpowiedź na tę, ponieważ daje to najlepszą opcję dla osób, które dzisiaj napotykają to pytanie. Dzięki za pbzip2wzmiankę. Jeśli link nie ładuje się dla nikogo innego, oto strona projektu i strona man .
Sundar - Przywróć Monikę

15

Zamiast gunzip w jednym kroku i bzip2 w innym, zastanawiam się, czy bardziej efektywne byłoby użycie rur. Coś jakgunzip --to-stdout foo.gz | bzip2 > foo.bz2

Myślę z dwoma lub więcej procesorami, to zdecydowanie byłoby szybsze. Ale może nawet z jednym rdzeniem. Jednak ze wstydem przyznaję, że tego nie wypróbowałem.


2
+1 za potokowanie, dyskowe we / wy to coś, czego chcesz uniknąć. Jeśli chodzi o kompresję, chyba że się mylę, bzip2 nie jest równoległy. Będziesz musiał użyć czegoś takiego jak pbzip2 do kompresji równolegle: kompresja.ca/pbzip2
gustafc

... i niestety wydaje się, że nie jest dostępne żadne narzędzie do dekompresji gzip równolegle.
gustafc

@gustafc: Dzięki za link do pbzip2, który był bardzo pomocny ... @OP: Unikałem przesyłania strumieniowego bcos Chcę mieć możliwość radzenia sobie z uszkodzonymi plikami GZ itp., nie tracąc ich w potoku ...
Sundar - Przywróć Monikę

4
@gustafc: Nawet jeśli bzip2i gzipnie działają równolegle wewnętrznie, za pomocą potoku możesz sprawić, aby działały równolegle, ponieważ potok domyślnie uruchamia dwa procesy, które będą działały równolegle. Tak więc przynajmniej dekompresja i kompresja będą działać równolegle.
śleske,

1
@sleske, nawet jeśli masz rację w teorii, bzip2użycie procesora przewyższa tę gunzip, więc w praktyce paralelizm, jaki tu osiągasz, jest minimalny. Mimo to nie trzeba wykonywać operacji dyskowych we / wy!
Johan Walles

6

GNU równoległy ( http://www.gnu.org/software/parallel ) może być opcją, jeśli masz wiele rdzeni (lub nawet wielu komputerów):

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

Przeczytaj stronę samouczka / podręcznika, aby uzyskać szczegółowe informacje i opcje.


3

To, co obecnie robisz, jest najlepszym wyborem. Nie ma dostępnego narzędzia do konwersji, a próba bzip2 już skompresowanego pliku nie jest tak naprawdę opcją, ponieważ często ma niepożądane skutki. Ponieważ algorytm jest inny, konwersja wymagałaby odzyskania oryginalnych danych niezależnie. Chyba że gzipping był krokiem w procesie bzip2, w którym niestety nie jest.


Nie algorytmy mają żadnych nakładających kroki takie, że mogę pominąć jeden krok w gzip dekompresji i to samo w bzip kompresji również?
Sundar - Przywróć Monikę

2
@sundar Nie sądzę. gzipużywa Leimpel-Ziv 77, a bzip2Burrows-Wheeler. Różne algorytmy, obawiam się.
new123456

2

Czasami muszę zrobić to samo z plikami dziennika. Najpierw zaczynam od najmniejszych plików * .gz ( ls -rS), gunzip, a następnie bzip2 osobno. Nie wiem, czy można skierować wyjście gunzip bezpośrednio na wejście bzip2. Polecenie bzip2 jest o wiele wolniejsze podczas kompresji niż gunzip podczas dekompresji, co może zajmować pamięć i zamieniać przestrzeń na hoście.

Ulepszenia lub sugestie są mile widziane. Oto mój jeden liniowiec:

for i in $(ls -rS *.gz | sed 's/\.gz//'); do gunzip ${i}.gz; bzip2 -9 ${i}; done

Dzięki za wkład, ważny jest punkt dotyczący różnicy prędkości między dwoma procesami i ich implikacji.
Sundar - Przywróć Monikę


1

Musiałem to zrobić kilka minut temu:

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

Gdzie rezipbyłoby zdefiniowane jako:

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

Opcjonalnie możesz też zrobić to wielowątkowo, używając -Popcji z xargs, ale bądź ostrożny z tym. (Zacznij nisko!)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.