Przekształć ścieżki archiwum tar bez wyodrębniania go

10

GNU tar(1)ma ciekawą opcję o nazwie --transform. Ze strony podręcznika:

--transform, --xform EXPRESSION
użyj sed replace EXPRESSION do transformacji nazw plików

Umożliwia to przekształcanie nazw ścieżek w locie podczas rozpakowywania archiwum, abyś mógł kontrolować, gdzie i jak zostanie on rozpakowany.

Moje pytanie brzmi: czy istnieje sposób przeprowadzenia podobnej transformacji in situ ; tzn. bez rozpakowywania archiwum?

Przykład

[user@host]$ tar tf test.tar
./foo/blah  ./foo/bleh
[user@host]$ some_deep_magic 's/foo/bar/' test.tar
[user@host]$ tar tf test.tar
./bar/blah  ./bar/bleh

Przypadek użycia

Dystrybuuję tararchiwum w zasadzie dla użytkowników końcowych, którzy nie mają pojęcia, i chciałbym, aby wyodrębnił je na właściwą ścieżkę bez ingerencji ode mnie. Staram się unikać trywialnego rozwiązania wypakowywania archiwum, zmiany nazw katalogów i przepakowywania, ponieważ archiwum jest duże.

Joseph R.
źródło
Dlaczego nie przekształcasz nazw podczas ich tworzenia?
Jose Luis Martin
@JoseLuisMartin Right. Mój przypadek użycia polega na tym, że archiwum już tam jest i, jak powiedziałem, chciałbym uniknąć rozpakowywania, przekształcania i przepakowywania.
Joseph R.
1
Możesz zmodyfikować strumień tar bez rozpakowywania go na dysk: github.com/mafintosh/tar-stream#modifying-existing-tarballs , perldoc.perl.org/5.10.1/Archive/Tar.html itp.
vladr

Odpowiedzi:

3

Możesz zamontować archiwum za pomocą archivemount lub mountavfs i ponownie je utworzyć

archivemount tarfile.tar /mnt
cd /mnt
tar cf /tmp/tarfile.tar --transform 's/foo/bar/' .

operacje zapisu w systemie plików archiwum dokonają pełnego przepisania na umount, więc nie wydają się dobrą opcją dla dużych plików.

EDYTOWAĆ

Nie znam szczegółów implementacji, ale wydaje mi się, że zapisujemy pliki zapisu do systemu plików.

Po prostu przetestuj, aby rozwiązać kolesie (ponad tar mojego / usr)

#!/bin/bash

# try to avoid slab cache issues 
cat /tmp/usr.tar > /dev/null

T="$(date +%s)"
tar xf /tmp/usr.tar
tar cf usr.tar usr --transform 's/usr/foo/'
T="$(($(date +%s)-T))"
echo "Tar/Untar seconds: ${T}"

T="$(date +%s)"
archivemount -o readonly -o nobackup /tmp/usr.tar /mnt
tar cf usr.tar /mnt  --transform 's/usr/foo/'
umount /mnt
T="$(($(date +%s)-T))"
echo "Archivemount seconds: ${T}"

T="$(date +%s)"
mountavfs
cd '/root/.avfs/tmp/usr.tar#'
tar cf /tmp/test/usr.tar   --transform 's/usr/foo/' .
T="$(($(date +%s)-T))"
echo "Avfs seconds: ${T}"

Wynik:

Tar/Untar seconds: 480
Archivemount seconds:  failure, a lot of read errors.
Avfs seconds: 217

Więc Avfs wygrywa! .

Jose Luis Martin
źródło
1
+1 Interesujące nowe polecenie. Ale czym różni się to podejście od rozpakowywania archiwum? Nie mówię o implementacji, ale o wydajności.
Joseph R.