Cambiar el nombre del directorio dentro de un archivo tar

14

¿Es posible cambiar el nombre de un directorio dentro de un archivo tar? Mi caso de uso es que tengo un archivo de especificación RPM provisto externamente que asume un tarball con una determinada estructura de directorio, y tengo un tarball proporcionado externamente cuyo nombre de directorio de nivel superior no coincide con lo que el archivo de especificación espera. No controlo ni el script que genera los tarballs ni el archivo de especificaciones RPM, por lo que no puedo hacer un cambio en ninguno de ellos para que coincida con el otro.

Lo que he estado haciendo es desmarcar, cambiar el nombre del directorio y luego crear un nuevo tarball, pero me preguntaba si había una alternativa para hacerlo.

Lorin Hochstein
fuente
3
Lamentablemente lo dudo, pero me interesaría ver si alguien más tiene un camino. Creo que su mejor opción es escribir un guión para descomprimir, renombrar y volver a escribir.
Kevin

Respuestas:

8

No debería ser muy difícil, al menos para los archivos que son compatibles con el formato antiguo donde los nombres de archivo se almacenan en un campo de tamaño fijo (100 bytes), pero no conozco ninguna herramienta que pueda cambiar el nombre de un archivo archivo en su lugar en un archivo tar. Además, con un archivo comprimido, necesitaría crear un nuevo archivo de todos modos.

Debería ser aún más fácil, pero no conozco ninguna herramienta existente que pueda filtrar un archivo, renombrar archivos a medida que avanza. Puede construir uno sobre las bibliotecas de tar en lenguajes de script; por ejemplo, aquí hay un script de prueba de concepto para cambiar el nombre de un directorio en un archivo tar usando Perl conArchive::Tar . El archivo se carga completamente en la memoria; Esta es una limitación intrínseca de 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 no tiene la capacidad de renombrar miembros sobre la marcha, pero pax(el reemplazo de POSIX para cpioy tar) sí. Sin embargo, no puede hacer que paxtanto leer como escribir desde un archivo. Lo que puede hacer es exponer el archivo como un árbol normal a través de AVFS y crear un nuevo archivo con pax. Esto retiene los nombres de los archivos (excepto los transformados), los contenidos, los tiempos y los modos, pero restablece la propiedad del archivo (a menos que se ejecute como root).

mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz
Gilles 'SO- deja de ser malvado'
fuente
GNU Tar ha tenido --transformdesde al menos 2010 que permite renombrar archivos sobre la marcha. Para ver un ejemplo, consulte: scriptsandoneliners.blogspot.com/2019/11/…
A.Danischewski el
@ A.Danischewski le --transformpermite cambiar el nombre de los archivos cuando crea o extrae un archivo. Pero, ¿cómo cambiar el nombre de los archivos en un archivo sin extraerlo? (La extracción no es una buena solución: es posible que no tenga suficiente espacio en el disco; es posible que no tenga los permisos para preservar la información de propiedad; es posible que no tenga la capacidad de preservar las marcas de tiempo exactamente ...)
Gilles 'SO- deja de ser malo'
De acuerdo, sí, acabo de ver que tu publicación dice que "GNU tar no tiene la capacidad de cambiar el nombre de los miembros sobre la marcha", lo hace, pero solo en el camino de entrada / salida. Si desea cambiar los nombres dentro de un archivo existente, puede usar archivemount para montarlo en un directorio, cambiar los nombres que desee y desmontarlo.
A.Danischewski
3

Tanto el truco de sr_ como la respuesta de Gilles se ven muy bien, pero si su problema es solo el nombre del directorio raíz del tarball objetivo, mientras ejecuta rpmbuild, una solución diferente podría ser redefinir la %setupmacro para hacer el cambio de nombre de directorio necesario.

Algo así como (que tendrá que adaptarse y perfeccionar esto a su configuración actual, en particular, la sustitución old-diry el desired-diry el uso de la herramienta de descompresión derecha) esta en su ~/.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 .

Honestamente no lo haría si no fuera en la situación más exótica, pero la tuya podría ser el caso :)

guido
fuente
1

Hack feo, pero tal vez esto te ayude, engañando tarcon enlaces simbólicos:

$ 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

Pensando en ello, probablemente no lo haga, ya rpmque no te dejará meterte con los argumentos tar, ¿verdad? (Editar: tal vez un tarscript de envoltorio complicado $PATHpodría ayudarlo a resolver esto).

sr_
fuente