Usuń pliki z archiwum tar

17

Mam duży plik, foo.tar.xzktóry zawiera dużo (powiedzmy 200000) plików. Doszedłem do wniosku, że to archiwum zawiera niektóre (około 5000) plików, których nie chcę. Nie mam wystarczającej ilości miejsca na dysku, aby zdekompresować całą zawartość na dysk; dodatkowo obawiam się, że atrybuty / prawa mogą zostać utracone, jeśli to zrobię. Mam jednak wystarczająco dużo miejsca, aby pomieścić dwie kopie skompresowanego archiwum. Czy istnieje narzędzie do usuwania niektórych plików z archiwum (określonych za pomocą wyrażenia regularnego w nazwie pliku) w locie, tj. Bez rozpakowywania archiwum do poszczególnych plików?

FUZxxl
źródło

Odpowiedzi:

15

GNU tar ma obecnie --deleteopcję, która działa również z archiwami.

Użyj tego w ten sposób, na przykład:

tar -vf yourArchive.tar --delete your/path/to/delete

Uwaga: najprawdopodobniej nie będzie działać na żadnym rodzaju taśmy magnetycznej. Ale tarnie ma problemów z działaniem w potoku, więc możesz po prostu użyć tymczasowego pliku tar i zastąpić go taśmą. To również nie będzie działać na skompresowanych plikach, więc musisz rozpakować plik.

Poza tym operacja będzie raczej powolna, ze względu na (z założenia) liniowy charakter archiwów tar.

Evi1M4chine
źródło
1
Istnieje, ale nie działa z plikami, w których losowy dostęp nie jest możliwy (np. Kompresja archiwów), ale to mój przypadek użycia.
FUZxxl,
1
Innym problemem jest to, że nie mogę określić wzorca do usunięcia. Proszę zwrócić uwagę na mój komentarz z 2013 r., W którym już omawiam niedociągnięcia gtar --delete.
FUZxxl,
4
@FUZxxl -Twspółpracuje z --delete, i --wildcardspozwala na używanie wzorców zamiast nazw plików, więc utwórz plik tymczasowy zawierający wzorce i użyj unxz < file.tar.xz | tar --wildcards --delete -T patternfile | xz > file2.tar.xz. Nie wykona pełnego wyrażenia regularnego (jeśli potrzebujesz, po prostu użyj tar -ti stwórz listę nazw plików do usunięcia), po prostu wzorce dopasowania nazw plików.
Random832,
14

(zredagowane, ponieważ źle zrozumiałem pytanie, które od tego czasu było również edytowane)

Najlepsze, co możesz zrobić, to wyodrębnić, usunąć i ponownie skompresować cały plik.

unxz < foobar-old.tar.xz | tar --delete foo/bar | xz > foobar-new.tar.xz

Nie można bezpośrednio usunąć plików z tar.

tar jest strumieniem, pierwotnie przeznaczonym dla napędów taśmowych, które nie szukają losowo - podczas gdy w systemie plików dyskowych możliwe jest wybicie dziury / przepisanie pozostałego pliku, przy kompresji punkt jest sporny, jak większość, jeśli nie wszystkie metody kompresji silnie zależą od zawartości, która pojawiła się wcześniej w pliku. Aby to zrobić, potrzebujesz bardzo szczegółowej wiedzy zarówno na temat metody kompresji, jak i formatu pliku tar. To złożoność do tego stopnia, że ​​nikt nawet nie zawracałby sobie tym głowy. Tańsze jest po prostu przechowywać pliki i ignorować je.

Jeśli potrzebujesz tej funkcji, tar prawdopodobnie nie jest tym, czego chcesz.

frostschutz
źródło
Pliki te stanowią 35% wielkości archiwów. Ograniczenia, które wskazałeś, najwyraźniej obowiązują tylko wtedy, gdy przepisuję plik, a nie jeśli modyfikuję go poza miejscem, co mogę zrobić (mam wystarczająco dużo miejsca, aby dwukrotnie zapisać spakowane archiwum). Czy istnieje takie narzędzie?
FUZxxl
Mogłem wtedy źle zrozumieć twoje pytanie. Jeśli mimo wszystko chcesz rozpakować plik tar i ponownie go spakować (po prostu bez tworzenia plików smołowanych - tj. Bezpośredniego potoku tar to tar), może to być możliwe.
frostschutz
Tak, mogę to zrobić. Po prostu pliki mają identyfikatory użytkownika / gids /, które muszę zachować. Ponadto nie mam wystarczającej ilości miejsca na dysku, aby zapisać rozpakowaną reprezentację. Mam jednak wystarczająco dużo miejsca, aby zapisać dwa spakowane archiwa.
FUZxxl
1
To wcale nie jest problem. Jeśli mogę to zrobić za jednym razem, czas nie będzie zbyt długi. Nie wyobrażam sobie żadnego formatu archiwum, który pozwalałby na szybkie usuwanie przy jednoczesnym zwolnieniu pamięci.
FUZxxl
1
--wildcardspomoc ... Musiałem jednak uwzględnić ./na początku wzoru ...
Gert van den Berg
-4

Zgodnie z instrukcją można przekazać listę nazw plików, taraby tylko je wyodrębnić. Na przykład:

$ tar --file archive.tar --list
foo
bar
baz

$ tar --file archive.tar --extract foo
Don Juan dePython
źródło
Nie rozumiem, jak - wyciąg pomaga mi. Czy mógłbyś opracować? Należy pamiętać, że nie mogę rozpakować archiwum (lub jego znacznej części) na dysk.
FUZxxl
2
Nie publikuj tylko linków: jest to wiki - dodaj wystarczającą treść, aby nie trzeba było opuszczać strony, aby zrozumieć twoją odpowiedź.
jasonwryan