Wie soll ich viele komprimierte Dateien in einem Archiv kombinieren?

10

Ich habe ein paar hundert .tar.xzDateien, die fast identisch sind (es handelt sich um tägliche Datenbank-Dumps, und die Datenbank ändert sich langsam).

Ich glaube, dass die unkomprimierten Dateien aufgrund der Ähnlichkeiten sehr gut komprimiert werden können, und Tests im kleinen Maßstab haben gezeigt, dass durch das Komprimieren einer beliebigen Anzahl dieser unkomprimierten Dateien ein Archiv erstellt wird, das nur geringfügig größer als eines von ihnen ist.

Mein Problem ist, dass alle unkomprimierten Dateien einige Terabyte groß sind (das Komprimierungsverhältnis beträgt etwa 25: 1), und ich habe nicht so viel Speicherplatz als Arbeitsbereich.

Gibt es eine Möglichkeit, die einzelnen komprimierten Dateien einzeln zu verarbeiten, sie einem einzelnen Archiv hinzuzufügen und die Vorteile der gemeinsamen Komprimierung beizubehalten?

jl6
quelle
Haben Sie versucht, Skripte zu erstellen, um eine Datei zu dekomprimieren, alle Dateien zu einem bestimmten Archiv hinzuzufügen und dann zum nächsten zu wechseln?
Darnir

Antworten:

10

Da TAR-Dateien ein Streaming-Format sind - Sie können catzwei davon zusammen erstellen und ein nahezu korrektes Ergebnis erzielen - müssen Sie sie dazu überhaupt nicht auf die Festplatte extrahieren. Sie können die Dateien (nur) dekomprimieren, miteinander verketten und diesen Stream erneut komprimieren:

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

combined.tar.xzwird ein komprimierter Tarball aller Dateien in den Komponententarballs sein, der nur geringfügig beschädigt ist. Zum Extrahieren müssen Sie die --ignore-zerosOption (in GNU tar) verwenden, da die Archive eine Markierung für das Dateiende haben, die in der Mitte des Ergebnisses angezeigt wird. Davon abgesehen wird jedoch alles korrekt funktionieren.

GNU tarunterstützt auch einen --concatenateModus zum Erstellen kombinierter Archive. Das hat die gleichen Einschränkungen wie oben - Sie müssen --ignore-zeroszum Extrahieren verwenden - aber es funktioniert nicht mit komprimierten Archiven. Sie können etwas aufbauen, um es durch Prozesssubstitution zum Arbeiten zu bringen, aber es ist mühsam und noch fragiler.

Wenn es Dateien gibt, die mehr als einmal in verschiedenen TAR-Dateien angezeigt werden, funktioniert dies nicht richtig, aber Sie haben dieses Problem trotzdem. Andernfalls erhalten Sie das, was Sie möchten. Wenn Sie die Ausgabe durchleiten, xzwird tardie Ausgabe ohnehin komprimiert.


Wenn Archive, die nur mit einer bestimmten tarImplementierung funktionieren, für Ihre Zwecke nicht geeignet sind, ist das Anhängen an das Archiv mit rIhr Freund:

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

Dadurch wird immer nur ein einzelnes Archiv extrahiert, sodass der Arbeitsbereich auf die Größe des Inhalts eines einzelnen Archivs beschränkt ist. Die Komprimierung wird so gestreamt, als wäre es gewesen, wenn Sie das endgültige Archiv auf einmal erstellt hätten. Es wird also so gut sein, wie es jemals hätte sein können. Sie führen eine Menge übermäßiger Dekomprimierung und Rekomprimierung durch, catwodurch dies langsamer als bei den Versionen wird. Das resultierende Archiv funktioniert jedoch überall ohne besondere Unterstützung.

Beachten Sie, dass - je nachdem, was genau Sie möchten - das Hinzufügen der unkomprimierten TAR-Dateien selbst zu einem Archiv möglicherweise ausreicht. Sie komprimieren (fast) genau so gut wie ihren Inhalt in einer einzelnen Datei und reduzieren den Komprimierungsaufwand für jede Datei. Das würde ungefähr so ​​aussehen:

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

Dies ist in Bezug auf die endgültige komprimierte Größe etwas weniger effizient, da der Stream zusätzliche Tar-Header enthält, spart jedoch Zeit beim Extrahieren und erneuten Hinzufügen aller Dateien als Dateien. Sie würden am Ende combined.tar.xzviele (unkomprimierte) db-*.tarDateien enthalten.

Michael Homer
quelle
Vielen Dank, Ihre zweite Option passt zu meinem Zweck, aber können Sie Ihren letzten Absatz näher erläutern? Wie würde das aussehen?
16.
@ jl6: Siehe Bearbeiten.
Michael Homer
Entschuldigung, konnte dies gerade erst testen. Ihre zweite Methode gibt mir diesen Fehler:tar: Cannot update compressed archives
jl6