Преобразование путей архива tar без его извлечения


10

У GNU tar(1)есть аккуратная опция под названием --transform. Со страницы руководства:

--transform, --xform EXPRESSION
использовать sed replace EXPRESSION для преобразования имен файлов

Это позволяет преобразовывать имена путей на лету во время извлечения архива, чтобы вы могли контролировать, где и как он будет извлечен.

У меня вопрос, есть ли способ выполнить аналогичное преобразование на месте ; т.е. без распаковки архива?

пример

[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

Случай использования

Я распространяю tarархив среди практически не знающих конечных пользователей и хотел бы, чтобы он извлекался по правильному пути без вмешательства со стороны меня. Я пытаюсь избежать тривиального решения по извлечению архива, переименованию каталогов и перепаковке, так как архив довольно большой.


Почему вы не трансформируете имена при его создании?
Хосе Луис Мартин

@JoseLuisMartin Верно. Мой пример использования: архив уже есть, и, как я уже сказал, я бы хотел избежать распаковки, преобразования и повторной упаковки.
Джозеф Р.

1
Вы можете изменить поток tar без фактического его извлечения на диск: github.com/mafintosh/tar-stream#modifying-existing-tarballs , perldoc.perl.org/5.10.1/Archive/Tar.html и т. Д.
vladr

Ответы:


3

Вы можете смонтировать архив с помощью archivemount или mountavfs и заново создать его

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

Операции записи в файловой системе архива выполнят полную перезапись на umount, так что не кажется хорошим вариантом для больших файлов.

РЕДАКТИРОВАТЬ

Я не знаю деталей реализации, но похоже, что мы сохраняем файлы записи на шаге файловой системы.

Просто проверьте, чтобы решить парни, (над tar моего / 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}"

Вывод:

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

Так что Avfs побеждает! ,


1
+1 Интересная новая команда. Но чем этот подход отличается от распаковки архива? Я говорю не о реализации, а о производительности.
Джозеф Р.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.