Transforme las rutas de un archivo tar sin extraerlo


10

GNU tar(1)tiene una opción ordenada llamada --transform. Desde la página del manual:

--transform, --xform EXPRESSION
usa sed replace EXPRESSION para transformar nombres de archivo

Esto permite la transformación de los nombres de ruta sobre la marcha a medida que se extrae el archivo para que pueda controlar dónde y cómo se extraerá.

Mi pregunta es, ¿hay alguna manera de realizar una transformación similar in situ ; es decir, sin extraer el archivo?

Ejemplo

[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

Caso de uso

Estoy distribuyendo un tararchivo a usuarios finales básicamente desorientados y me gustaría que se extraiga en la ruta correcta sin interferencia de mi parte. Estoy tratando de evitar la solución trivial de extraer el archivo, cambiar el nombre de los directorios y volver a empaquetar ya que el archivo es grande.


¿Por qué no transforma los nombres al crearlo?
Jose Luis Martin

@JoseLuisMartin Derecha. Mi caso de uso es que el archivo ya está allí y, como dije, me gustaría evitar desempacar, transformar y reempacar.
Joseph R.

1
Puede modificar el flujo de alquitrán sin extraerlo en el disco: github.com/mafintosh/tar-stream#modifying-existing-tarballs , perldoc.perl.org/5.10.1/Archive/Tar.html , etc.
vladr

Respuestas:


3

Puede montar el archivo con archivemount o mountavfs y volver a crearlo

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

las operaciones de escritura en el sistema de archivos archivados realizarán una reescritura completa en umount, por lo que no parece una buena opción para archivos grandes.

EDITAR

No conozco los detalles de implementación, pero parece que estamos guardando los archivos de escritura en el paso del sistema de archivos.

Simplemente pruebe para resolver tipos, (sobre un alquitrán de mi / 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}"

Salida:

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

¡Entonces Avfs gana! .


1
+1 Interesante nuevo comando. Pero, ¿en qué se diferencia este enfoque de desempacar el archivo? No estoy hablando de implementación inteligente, sino de rendimiento.
Joseph R.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.