Renomeia o diretório dentro de um arquivo tar

14

É possível renomear um diretório dentro de um arquivo TAR? Meu caso de uso é que eu tenho um arquivo de especificação RPM fornecido externamente que assume um tarball com uma determinada estrutura de diretório e tenho um tarball fornecido externamente cujo nome de diretório de nível superior não corresponde ao que o arquivo de especificação espera. Eu não controlo o script que gera os tarballs ou o arquivo de especificação do RPM, então não posso fazer uma alteração em nenhum deles para corresponder ao outro.

O que eu tenho feito é descompactar, alterar o nome do diretório e criar um novo tarball, mas fiquei me perguntando se havia uma alternativa para fazer isso.

    
por Lorin Hochstein 05.12.2011 / 15:03

4 respostas

8

Não deve ser muito difícil, pelo menos para arquivos compatíveis com o formato antigo, no qual os nomes de arquivos são armazenados em um campo de tamanho fixo (100 bytes), mas não conheço nenhuma ferramenta que pode renomear um arquivo no lugar em um arquivo tar. Além disso, com um arquivo compactado, você precisaria criar um novo arquivo de qualquer maneira.

Deve ser ainda mais fácil, mas eu não conheço nenhuma ferramenta existente que possa filtrar um arquivo, renomeando os arquivos como ele é. Você pode criar uma sobre bibliotecas de tar em linguagens de script; por exemplo, aqui está um script de prova de conceito para renomear um diretório em um arquivo tar usando Perl com Archive::Tar . O arquivo é carregado inteiramente na memória; essa é uma limitação 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);

O GNU tar não tem a capacidade de renomear membros na hora, mas pax (o substituto de POSIX para cpio e tar ) faz. No entanto, você não pode fazer pax ler e escrever em um arquivo. O que você pode fazer é expor o arquivo como uma árvore comum através do AVFS e criar um novo arquivo com pax . Isso retém os nomes dos arquivos (exceto quando transformados), conteúdo, tempos e modos, mas redefine a propriedade do arquivo para você (a menos que seja executado como root).

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

Tanto o hack do sr_ quanto o do Gilles parecem muito bons, mas se o seu problema é apenas o nome do diretório raiz do tarball de destino, enquanto executa o rpmbuild, uma solução diferente poderia ser redefinir a macro %setup para fazer o necessário renomear dir.

Algo como (você terá que adaptar e refinar isso para a sua configuração real, em particular substituindo old-dir e desired-dir e usando a ferramenta de descompactação correta) em ~/.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 .

Eu honestamente não faria isso se não fosse na situação mais exótica, mas o seu poderia ser o caso:)

    
por 05.12.2011 / 22:13
2

Basta ver esta página, mas encontrou a resposta correta em outro lugar:

link

Ele diz que você pode passar -n para a macro% setup para informar ao rpmbuild o nome da pasta de nível superior dentro do tarball

    
por 31.08.2012 / 15:22
1

Hack feio, mas talvez isso ajude você, enganando tar com links 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 nisso, provavelmente não, já que rpm não vai deixar você mexer com os argumentos para tar , seria? (Edit: talvez algum script% wrapper tar em $PATH possa te ajudar com isso.)

    
por 05.12.2011 / 16:18

Tags