Перетворення файлів gzip в bzip2 ефективно


10

У мене є маса файлів gzip, які мені доводиться час від часу перетворювати на bzip2. В даний час я використовую скрипт оболонки, який просто 'gunzip кожен файл, а потім' bzip2. Хоча це працює, для завершення потрібно багато часу.

Чи можна зробити цей процес більш ефективним? Я готовий здійснити занурення і вивчити вихідні коди gunzip та bzip2, якщо потрібно, але я просто хочу бути впевненим у виграші. Чи є надія на підвищення ефективності процесу?

Відповіді:


1

Це питання було задано дуже давно, коли pbzip2 або не був доступний, або не міг стискатися зі stdin, але тепер ви можете паралелізувати як стискання, так і стиснення, використовуючи паралелі та pbzip2 (замість bzip2 ):

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

що значно швидше, ніж використання bzip2 .


Привіт, я змінив прийняту відповідь на цю, оскільки це дає найкращий варіант для людей, які сьогодні натрапляють на питання. Дякую за pbzip2згадку. Якщо посилання не завантажується ні для кого іншого, ось сторінка проекту та довідкова сторінка .
sundar

15

Замість того, щоб gunzip в один крок і bzip2 в іншому, мені цікаво, чи не було б більш ефективно використовувати труби. Щось на зразокgunzip --to-stdout foo.gz | bzip2 > foo.bz2

Я думаю з двома або більше процесорами, це, безумовно, буде швидше. Але, можливо, навіть лише з одним ядром. Я ганебно признаюсь, що не пробував цього.


2
+1 для трубопроводів, дискового вводу / виводу - це те, чого ви хочете уникати. Що стосується стиснення, якщо я не помиляюся, bzip2 не є паралельним. Вам потрібно буде використовувати щось на кшталт pbzip2, щоб стиснути паралель: compression.ca/pbzip2
gustafc

... і, на жаль, начебто не існує жодної утиліти для декомпресії паралельної gzip.
gustafc

@gustafc: Дякую за посилання на pbzip2, це було дуже корисно ... @OP: Я ухилявся від передачі файлів bcos, я хочу мати можливість мати справу з пошкодженими файлами gz тощо, не втрачаючи їх у трубі ...
sundar

4
@gustafc: Навіть якщо bzip2і gzipне працюють паралельно всередині, використовуючи трубу, ви можете змусити їх працювати паралельно, оскільки труба неявно запускає два процеси, які будуть працювати паралельно. Тож принаймні декомпресія та стискання будуть працювати паралельно.
sleske

1
@sleske, хоч ти і теоретично правий, bzip2використання процесора використовує карлики gunzip, тому на практиці паралелізм, який ви отримуєте тут, мінімальний. Не потрібно робити IO на диску все ж приємно!
Йохан Уоллес

6

Паралель GNU ( http://www.gnu.org/software/parallel ) може бути варіантом, якщо у вас є кілька ядер (або навіть декілька машин):

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

Прочитайте сторінку підручника / man для детальної інформації та параметрів.


3

Що ви зараз робите, це ваша найкраща ставка. Немає інструменту перетворення, і спроба bzip2 вже gzipped файл насправді не є варіантом, оскільки це часто має небажані ефекти. Оскільки алгоритм інший, перетворення передбачає отримання вихідних даних незалежно. Якщо, звичайно, gzipping був кроком у процесі bzip2, в якому це, на жаль, не є.


Хіба алгоритми не мають жодних кроків, що перекриваються таким чином, щоб я міг пропустити один крок у декомпресії gzip і той самий при стисненні bzip?
sundar

2
@sundar Я б не вважав цього. gzipвикористовує Leimpel-Ziv 77, тоді як bzip2використовує Burrows-Wheeler. Боюся різних алгоритмів.
new123456

2

Інколи мені потрібно робити те ж саме з файлами журналів. Я починаю з найменших файлів * .gz спочатку ( ls -rS), gunzip, а потім і bzip2 окремо. Я не знаю, чи можна направити вихід gunzip безпосередньо на вхід bzip2. Команда bzip2 настільки повільніше при стисненні, ніж gunzip знаходиться при декомпресії, що може зайняти пам'ять і поміняти місця на хості.

Вдосконалення чи пропозиції вітаються. Ось мій один вкладиш:

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

Дякую за вклад, важливим є питання про різницю швидкості між двома процесами та її наслідки.
sundar


1

Просто довелося це зробити кілька хвилин тому:

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

Де rezipбуло б визначено як:

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

За бажанням, ви також можете зробити його багатопотоковим, скориставшись -Pопцією з xargs, але будьте обережні з цим. (Почніть низько!)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.