Zmień nazwę katalogu w archiwum tar

14

Czy można zmienić nazwę katalogu wewnątrz archiwum tar? Mój przypadek użycia polega na tym, że mam dostarczony zewnętrznie plik specyfikacji RPM, który zakłada plik tar z pewną strukturą katalogów, i mam dostarczony zewnętrznie plik tarball, którego nazwa katalogu najwyższego poziomu nie jest zgodna z oczekiwaniami pliku spec. Nie kontroluję ani skryptu, który generuje pliki archiwów, ani pliku specyfikacji RPM, więc nie mogę zmienić żadnego z nich, aby pasował do drugiego.

To, co robiłem, to rozpakowywanie, zmiana nazwy katalogu, a następnie tworzenie nowego archiwum, ale zastanawiałem się, czy istnieje alternatywa.

Lorin Hochstein
źródło
3
Niestety wątpię w to, ale byłbym zainteresowany, aby sprawdzić, czy ktoś inny ma sposób. Myślę, że najlepszym rozwiązaniem jest napisanie skryptu do rozpakowywania, zmiany nazwy i zmiany tar.
Kevin,

Odpowiedzi:

8

Nie powinno to być bardzo trudne, przynajmniej dla archiwów zgodnych ze starym formatem, w których nazwy plików są przechowywane w polu o stałym rozmiarze (100 bajtów), ale nie znam żadnego narzędzia, które mogłoby zmienić nazwę plik na miejscu w archiwum tar. Poza tym przy skompresowanym archiwum i tak musisz utworzyć nowy plik.

Powinno to być jeszcze łatwiejsze, ale nie znam żadnego istniejącego narzędzia, które mogłoby filtrować archiwum, zmieniając nazwy plików w miarę upływu czasu. Możesz zbudować jeden na bibliotekach tar w językach skryptowych; na przykład, oto skrypt sprawdzający koncepcję, aby zmienić nazwę katalogu w archiwum tar za pomocą Perla zArchive::Tar . Archiwum jest ładowane całkowicie do pamięci; jest to nieodłączne ograniczenie Archive::Tar.

#!/usr/bin/env perl
## Usage: tar-rename OLDPREFIX NEWPREFIX
use strict;
use warnings;
use Archive::Tar;
my ($from, $to) = @ARGV;
my $tar = Archive::Tar->new(\*STDIN);
foreach my $file ($tar->get_files()) {
    my $name = $file->name;
    $name =~ s~\A\Q$from\E($|/)~$to$1~;
    $file->rename($name) unless $name eq $file->name;
}
$tar->write(\*STDOUT);

GNU tar nie ma możliwości zmiany nazwy członków w locie, ale pax(zastępuje POSIX na cpioi tar) ma. Nie można jednak paxzarówno czytać, jak i pisać z archiwum. Możesz udostępnić archiwum jako zwykłe drzewo za pośrednictwem systemu AVFS i utworzyć nowe archiwum za pomocą pax. To zachowuje nazwy plików (z wyjątkiem przekształconych), zawartość, czasy i tryby, ale resetuje własność pliku (chyba że jest wykonywany jako root).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz
Gilles „SO- przestań być zły”
źródło
GNU Tar ma --transformco najmniej od 2010 roku, który pozwala na zmianę nazw plików w locie. Na przykład patrz: scriptsandoneliners.blogspot.com/2019/11/…
A.Danischewski
@ A.Danischewski --transformpozwala zmieniać nazwy plików podczas budowania lub rozpakowywania archiwum. Ale jak zmienić nazwy plików w archiwum bez rozpakowywania go? (Wyodrębnianie nie jest dobrym rozwiązaniem: możesz nie mieć wystarczającej ilości miejsca na dysku; możesz nie mieć uprawnień do zachowania informacji o własności; możesz nie mieć możliwości zachowania znaczników czasu dokładnie ...)
Gilles „SO- przestań być zły”
Okej, tak, właśnie widziałem twój post informujący, że „tar GNU nie ma możliwości zmiany nazwy członków w locie” - robi to, ale tylko po wejściu / wyjściu. Jeśli chcesz zmienić nazwy w istniejącym archiwum, możesz użyć archivemount, aby zamontować go w katalogu, zmienić dowolne nazwy i odmontować je.
A.Danischewski
3

Zarówno hack sr_, jak i odpowiedź Gillesa wyglądają bardzo dobrze, ale jeśli twoim problemem jest tylko nazwa katalogu głównego docelowego archiwum tar, podczas uruchamiania rpmbuild, innym rozwiązaniem może być ponowne zdefiniowanie %setupmakra w celu przeprowadzenia wymaganej zmiany nazwy katalogu.

Coś jak (będziesz musiał dostosować i udoskonalić to do aktualnej konfiguracji, w szczególności zastępując old-dira desired-diri za pomocą odpowiedniego narzędzia dekompresji) to w twojej ~/.rpmmacros:

%setup cd ../BUILD \
rm -rf cd-player \
bunzip2 -dc ../SOURCES/%{name}-%{version}.tar.bz2 | tar -xvvf - \
if [ $? -ne 0 ]; then \
  exit $? \
fi \
mv <old-dir> <desired-dir> \
cd <desired-dir> \
cd ../BUILD/cd-player \
chmod -R a+rX,g-w,o-w .

Szczerze mówiąc, nie zrobiłbym tego, gdyby nie najbardziej egzotyczna sytuacja, ale twoja może tak być :)

guido
źródło
1

Brzydki hack, ale może ci to pomóc, oszukiwanie za tarpomocą dowiązań symbolicznych:

$ mkdir a b
$ date >> b/foo
$ tar zcvf b-foo.tgz b/foo
$ rm -rf b
$ ln -s a b

$ tar zxvf b-foo.tgz                                                              
x b/foo: Cannot extract through symlink b
tar: Error exit delayed from previous errors.
$ tar zxvPf b-foo.tgz                                                             
x b/foo
$ ls a
foo

Myśląc o tym, prawdopodobnie tak nie jest, ponieważ rpmnie pozwoli ci zadzierać z argumentami tar, prawda? (Edycja: może jakiś trudny tarskrypt otoki $PATHmoże pomóc ci to obejść.)

sr_
źródło