Transforme os caminhos de um arquivo tar sem extraí-lo


10

O GNU tar(1)tem uma opção elegante chamada --transform. Na página do manual:

--transform, --xform EXPRESSION
usa sed replace EXPRESSION para transformar nomes de arquivos

Isso permite a transformação de nomes de caminhos em tempo real à medida que o arquivo está sendo extraído, para que você possa controlar onde e como será extraído.

Minha pergunta é: existe uma maneira de realizar uma transformação semelhante in situ ; ou seja, sem extrair o arquivo?

Exemplo

[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

Estou distribuindo um tararquivo para usuários finais basicamente sem noção e gostaria que ele fosse extraído no caminho correto sem interferência de mim. Estou tentando evitar a solução trivial de extrair o arquivo morto, renomear os diretórios e reembalar, pois o arquivo é amplo.


Por que você não transforma nomes ao criá-lo?
Jose Luis Martin

@JoseLuisMartin Right. Meu caso de uso é que o arquivo já está lá e, como eu disse, gostaria de evitar a descompactação, transformação e reembalagem.
Joseph R.

1
Você pode modificar o fluxo tar sem realmente extraí-lo para o disco: github.com/mafintosh/tar-stream#modifying-existing-tarballs , perldoc.perl.org/5.10.1/Archive/Tar.html , etc.
vladr

Respostas:


3

Você pode montar o arquivo morto com archivemount ou mountavfs e recriá-lo novamente

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

As operações de gravação no sistema de arquivos do archive realizarão uma reescrita completa em umount, portanto, não pareça uma boa opção para arquivos grandes.

EDITAR

Não sei os detalhes da implementação, mas parece que estamos salvando os arquivos de gravação na etapa do sistema de arquivos.

Apenas teste para resolver caras, (acima de um alcatrão do meu / 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}"

Resultado:

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

Então o Avfs vence! .


1
+1 Novo comando interessante. Mas como essa abordagem é diferente de descompactar o arquivo? Não estou falando de implementação, mas de desempenho.
Joseph R.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.