Як слід об'єднати багато стислих файлів в один архів?


10

У мене є кілька сотень .tar.xzфайлів, які майже однакові (вони щодня скидають базу даних, і база даних змінюється повільно).

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

Моя проблема полягає в тому, що всі нестиснені файли мали б кілька терабайт (коефіцієнт стиснення близько 25: 1), і у мене немає стільки дискового простору, щоб використовувати його як робочу область.

Чи є спосіб я обробляти окремі стислі файли один за одним, додаючи їх до єдиного архіву та зберігаючи переваги стиснення їх разом?


Ви спробували його записати, щоб ви розпакували один файл, додали всі файли до заданого архіву, а потім перейшли до наступного?
darnir

Відповіді:


10

Оскільки файли tar є потоковим форматом - ви можете їх catдва разом і отримати майже правильний результат - для цього вам не потрібно витягувати їх на диск. Ви можете розпаковувати (лише) файли, об'єднувати їх разом і повторно стискати цей потік:

xzcat *.tar.xz | xz -c > combined.tar.xz

combined.tar.xzбуде стислим тарболом усіх файлів у складі tarballs, які лише незначно пошкоджені. Для вилучення вам доведеться скористатися --ignore-zerosопцією (в GNU tar), оскільки в архівах є маркер "кінця файлу", який з’явиться посередині результату. Крім цього, все буде працювати правильно.

GNU tarтакож підтримує --concatenateрежим створення комбінованих архівів. Це має ті ж обмеження, що і вище - ви повинні використовувати --ignore-zerosдля вилучення, але це не працює зі стислими архівами. Ви можете створити щось, щоб наштовхнути його на роботу, використовуючи процес заміни, але це клопоту і ще більш крихко.

Якщо є файли, які не раз з'являються в різних файлах tar, це не спрацює належним чином, але проблема у вас є незалежно. В іншому випадку це дасть вам те, що ви хочете - трубопровідний результат xz- це те, як tarстисне його вихід у будь-якому випадку.


Якщо архіви, які працюють лише з певною tarреалізацією, не відповідають вашим цілям, додавши до архіву rваш друг:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    mkdir tmp
    pushd tmp
    tar xJf "../$x"
    tar rJf ../combined.tar.xz .
    popd
    rm -r tmp
done

Це лише витягує один архів за один раз, тому робочий простір обмежений розміром вмісту одного архіву. Стиснення протікає так, як це було б, якби ви зробили остаточний архів усі відразу, тож він буде настільки ж гарний, як і колись міг бути. Ви робите багато зайвої декомпресії та рекомпресії, що зробить це повільніше, ніж catверсії, але отриманий архів буде працювати де завгодно без особливої ​​підтримки.

Зауважте, що - залежно від того, що саме ви хочете - достатньо лише додавання самих нестиснених файлів tar до архіву. Вони стиснуть (майже) точно так само, як і їх вміст в одному файлі, і це зменшить накладні витрати на стиснення для кожного файлу. Це виглядатиме приблизно так:

tar cJf combined.tar.xz dummy-file
for x in db-*.tar.xz
do
    xz -dk "$x"
    tar rJf combined.tar.xz "${x%.xz}"
    rm -f "${x%.xz}"
done

Це дещо менш ефективно з точки зору остаточного стисненого розміру, оскільки в потоці є додаткові заголовки дьогтю, але економиться час на витяг та повторне додавання всіх файлів у вигляді файлів. У вас є combined.tar.xzбагато (нестиснених) db-*.tarфайлів.


Дякую, ваш другий варіант відповідає моїй меті, але ви могли б детальніше зупинитися на своєму останньому абзаці? Як би це виглядало?
jl6

@ jl6: Див. редагування.
Майкл Гомер

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