Ganti nama direktori di dalam arsip tar

14

Apakah mungkin untuk mengganti nama direktori di dalam arsip tar? Kasus penggunaan saya adalah bahwa saya memiliki file spesifikasi RPM yang disediakan secara eksternal yang mengasumsikan tarball dengan struktur direktori tertentu, dan saya memiliki tarball yang disediakan secara eksternal yang nama direktori tingkat atasnya tidak cocok dengan yang diharapkan oleh file spesifikasi. Saya tidak mengontrol skrip yang menghasilkan tarbal atau file spesifikasi RPM, jadi saya tidak bisa membuat perubahan pada salah satu yang cocok dengan yang lain.

Apa yang telah saya lakukan adalah menghapus tanda, mengubah nama direktori, dan kemudian membuat tarball baru, tetapi saya bertanya-tanya apakah ada alternatif untuk melakukan itu.

Lorin Hochstein
sumber
3
Sayangnya saya ragu, tapi saya akan tertarik untuk melihat apakah ada orang lain yang punya cara. Saya pikir cara terbaik Anda adalah menulis skrip untuk untar, ganti nama, dan tar ulang.
Kevin

Jawaban:

8

Seharusnya tidak terlalu sulit, setidaknya untuk arsip yang kompatibel dengan format gaya lama di mana nama file disimpan dalam bidang ukuran tetap (100 byte), tapi saya tidak tahu alat apa pun yang dapat mengubah nama menjadi file di tempat dalam arsip tar. Selain itu, dengan arsip terkompresi, Anda harus membuat file baru.

Seharusnya lebih mudah, tapi saya tidak tahu ada alat yang bisa menyaring arsip, mengganti nama file saat berjalan. Anda dapat membangun satu di atas pustaka tar dalam bahasa scripting; misalnya, inilah skrip pembuktian konsep untuk mengganti nama direktori dalam arsip tar menggunakan Perl denganArchive::Tar . Arsip dimuat seluruhnya ke dalam memori; ini adalah batasan intrinsik dari 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 tidak memiliki kemampuan untuk mengganti nama anggota on the fly, tetapi pax(pengganti POSIX untuk cpiodan tar) tidak. Namun, Anda tidak dapat membuat paxkeduanya membaca dan menulis dari arsip. Yang dapat Anda lakukan adalah mengekspos arsip sebagai pohon biasa melalui AVFS , dan membuat arsip baru dengan pax. Ini mempertahankan nama file (kecuali sebagai ditransformasikan), konten, waktu dan mode tetapi mengatur ulang kepemilikan file kepada Anda (kecuali dieksekusi sebagai root).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz
Gilles 'SANGAT berhenti menjadi jahat'
sumber
GNU Tar telah memiliki --transformsetidaknya sejak 2010 yang memungkinkan penggantian nama file dengan cepat. Sebagai contoh, lihat: scriptsandoneliners.blogspot.com/2019/11/...
A.Danischewski
@ A.Danischewski --transformmemungkinkan Anda mengubah nama file saat membuat atau mengekstrak arsip. Tetapi bagaimana Anda mengganti nama file dalam arsip tanpa mengekstraksinya? (Mengekstrak bukanlah solusi yang baik: Anda mungkin tidak memiliki ruang disk yang cukup; Anda mungkin tidak memiliki izin untuk menyimpan informasi kepemilikan; Anda mungkin tidak memiliki kemampuan untuk melestarikan stempel waktu dengan tepat ...)
Gilles 'SANGAT berhenti menjadi jahat'
Oke, ya saya baru saja melihat pos Anda menyatakan bahwa "GNU tar tidak memiliki kemampuan untuk mengubah nama anggota dengan cepat" - tetapi hanya pada saat masuk / keluar. Jika Anda ingin mengubah nama di dalam arsip yang ada, Anda dapat menggunakan archivemount untuk memasangnya ke direktori, ubah nama apa pun yang Anda inginkan dan hapus pemasangannya.
A.Danischewski
3

Kedua hack sr_ dan jawaban Gilles terlihat sangat baik, tetapi jika masalah Anda hanyalah nama direktori root dari tarball target, saat menjalankan rpmbuild, solusi yang berbeda dapat mendefinisikan ulang %setupmakro untuk melakukan penggantian nama dir yang diperlukan.

Sesuatu seperti (Anda harus menyesuaikan dan memperbaiki ini dengan konfigurasi Anda yang sebenarnya, khususnya mengganti old-dirdan desired-dirdan menggunakan alat dekompresi yang tepat) ini di Anda ~/.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 .

Saya tidak akan jujur ​​melakukan itu jika tidak dalam situasi yang paling eksotis, tetapi Anda bisa menjadi masalahnya :)

guido
sumber
1

Retas yang jelek, tapi mungkin ini bisa membantu Anda, membodohi tarsymlink:

$ 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

Berpikir tentang itu, mungkin tidak, karena rpmtidak akan membiarkan Anda mengacaukan argumen tar, kan? (Sunting: mungkin beberapa tarskrip pembungkus rumit $PATHdapat membantu Anda mengatasi hal ini.)

sr_
sumber