Scripting multi-volume (GNU) 'tar' com número predefinido de volumes

0

Eu escrevi um pequeno script para testar (ou extrair) um muito grande arquivo tar de vários volumes (nota: criado com o GNU tar ), cada um dos quais 00x.tar chunk vai caber em um DVD padrão:

#!/bin/bash
d=$(dirname $0)
prf="someprefix"
last=$(ls -1 $d/*.tar | wc -l)

for i in $(eval echo {2..$last}); do echo "n $prf.00$i.tar"; done | tar -Mtvf ./$prf.001.tar --wildcards "$1"

Notas:

  • O canal tar funcionará com ou sem o parâmetro $1 fornecido.
  • O d local ajudará no caso em que o volume e este script estão em outro local, mas é executado a partir de um diretório arbitrário, e. g. seu código%.
  • O $HOME local contornará o problema do GNU last para nunca verificar o número de volumes disponíveis no diretório de trabalho.
  • Neste tamanho enorme, tar dificilmente será maior que 5 (muito menos 9) - daí o $last .

OK, isso funciona. Mas livrar-se completamente do loop seria mesmo melhor.
Assim ( 00 deixado de fora):

 eval echo -e "n\ $d/$prf.00{2..$last}.tar\\n" | tar -Mtvf ./$prf.001.tar

No entanto, isso só funciona com exatamente dois volumes. Defina --wildcards ... para e. g. 4, e outro problema será exibido por last quando o pipe for omitido para um teste:

n someprefix.002.tar
 n someprefix.003.tar
 n someprefix.004.tar

Ugh! Como esse espaço em branco chegou lá? echo não gosta disso.

Uma "correção" (embora muito agressiva) é " tar out" do espaço em branco inserindo um sed no canal acima. Muito feio, mas para o inferno, funciona. :)

O espaço em branco não pode ser evitado em primeiro lugar também?

( | sed 's/^ //' pode não ser uma boa solução aqui, porque precisaríamos de um caractere substituto (por exemplo, tr ) para preservar o primeiro espaço após o § ; salvar de hacks sujos, não é possível dizer n "traduzir tudo _but_ o primeiro espaço".)

    
por syntaxerror 27.11.2014 / 11:01

1 resposta

2
$ eval echo -e "n\ $d/$prf.00{2..$last}.tar\\n"
n someprefix.002.tar
 n someprefix.003.tar
 n someprefix.004.tar

How did that whitespace get in there?

A resposta em poucas palavras: isso é análogo ao resultado que você obteria se fizesse eco de uma linha usando a expansão de nome de arquivo em um monte de arquivos cujos nomes terminam com nova linha.

Conforme descrito na expansão de chaves :

Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence expression between a pair of braces, followed by an optional postscript.

Então o shell está avaliando

echo -e n\ dir/prefix00{2..4}.tar\n
        ^preamble^^^^^^      ^postscript

E, como na expansão de nome de arquivo, insere um espaço entre cada elemento expandido , assim você obtém (estou mantendo a sequência de escape \ n aqui para maior clareza):

n dir/prefix002.tar\n n dir/prefix003.tar\n n dir/prefix004.tar\n\n

QED.

Quanto à sua pergunta básica de como, em um script, alimentar tar a informação para passar por vários volumes, aqui estão duas maneiras:

  • Use seq para gerar os comandos n :
    seq -f "n $d/$prf.%03g.tar" 2 $last | tar -Mtvf $d/$prf.001.tar
  • Escreva um script curto para gerar cada novo nome de volume e passe-o à tar ' --new-volume-script option:
    echo '#!/bin/sh' > ./newvol
    echo "printf $d/$prf.%03d.tar \$TAR_VOLUME >&\$TAR_FD" >> ./newvol
    chmod +x ./newvol
    tar -Mtvf $d/$prf.001.tar --new-volume-script=./newvol
    
por 29.11.2014 / 00:35