Перейменуйте каталог всередині архіву дьогтю


14

Чи можливо перейменувати каталог всередині архіву tar? Мій випадок використання полягає в тому, що у мене є зовнішній файл специфікації RPM, який передбачає тарбол з певною структурою каталогу, і у мене є наданий зовнішньо тарбол, ім'я каталогів верхнього рівня якого не відповідає тому, що очікує файл специфікації. Я не контролюю ні сценарій, який генерує тарболи, ні специфікаційний файл RPM, тому не можу змінити жоден з них, щоб відповідати іншому.

Те, що я роблю, - це зняти знімок, змінити ім'я каталогів, а потім створити новий тарбол, але мені було цікаво, чи існує альтернатива цьому.


3
На жаль, я сумніваюся в цьому, але мені було б цікаво подивитися, чи є у когось іншого спосіб. Я думаю, що найкраще зробити, щоб написати сценарій, щоб untar, перейменовувати та повторно tar.
Кевін

Відповіді:


8

Це не повинно бути дуже складно, принаймні для архівів, сумісних із старим форматом, де імена файлів зберігаються у полі фіксованого розміру (100 байт), але я не знаю жодного інструменту, який може перейменувати файл на місці в архіві смоли. Крім того, зі стиснутим архівом вам все одно потрібно буде створити новий файл.

Це може бути ще простіше, але я не знаю жодного існуючого інструменту, який би міг фільтрувати архів, перейменувавши файли, як йде. Ви можете побудувати його поверх бібліотек tar на мовах скриптів; наприклад, ось сценарій перевірки концепції перейменування каталогу в архіві tar, використовуючи Perl зArchive::Tar . Архів повністю завантажується в пам'ять; це внутрішнє обмеження 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 не має можливості перейменовувати членів на ходу, але pax(заміна POSIX на cpioта tar). Однак ви не можете змусити paxчитати і записувати з архіву. Що ви можете зробити, це відкрити архів як звичайне дерево через AVFS та створити новий архів за допомогою pax. Це зберігає назви файлів (крім трансформованих), вмісту, часу та режимів, але скидає право власності на файл (якщо не виконується як root).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz

З 2010 року GNU Tar розпочав --transformперейменування файлів на ходу. Для прикладу дивіться: scriptptsandoneliners.blogspot.com/2019/11/…
A.Danischewski

@ A.Danischewski --transformдозволяє перейменовувати файли під час створення або вилучення архіву. Але як перейменувати файли в архів, не витягаючи його? (Витяг не є хорошим рішенням: у вас може бути недостатньо місця на диску; у вас може не бути дозволів на збереження інформації про право власності; можливо, ви не зможете точно зберігати часові позначки ...)
Жил "SO - перестаньте бути злим"

Гаразд, так, я щойно побачив ваш пост, який стверджує, що "GNU tar не має змоги перейменовувати членів на ходу" - це відбувається, але лише під час входу / виходу. Якщо ви хочете змінити імена в існуючому архіві, ви можете використовувати archivemount для встановлення його до каталогу, змінити всі імена, які ви хочете, і відключити їх.
A.Danischewski

3

І хакер sr_, і відповідь Гілла виглядають дуже добре, але якщо вашою проблемою є лише ім'я кореневого каталогу цільової тарболу, під час запуску rpmbuild, іншим рішенням може бути повторне визначення %setupмакросу, щоб зробити необхідне перейменування dir.

Щось подібне (ви повинні адаптувати і уточнити це в вашій фактичної конфігурації, зокрема , заміна old-dirі desired-dirі використовувати правильний інструмент декомпресії) це в ~/.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 .

Я б не чесно робив це, якби не в самій екзотичній ситуації, але ваше може бути так :)


2

Просто перегляньте цю сторінку, але знайшли належну відповідь в іншому місці:

http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html

Це говорить про те, що ви можете передати -n до% макросу налаштування, щоб повідомити rpmbuild ім'я папки верхнього рівня в tarball


1

Некрасивий злом, але, можливо, це вам допоможе, обдуривши tarсимволічні посилання:

$ 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

Думаючи про це, напевно, це не так, як rpmце не дозволить вам заплутатися з аргументами tar, чи не так? (Редагувати: можливо, якийсь складний tarсценарій обгортки у $PATHвас може обійти це питання.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.