Como fazer o globbing do tar funcionar com a opção 'change directory'

8

Eu tenho a seguinte estrutura de diretório:

base/
   files/
   archives/
   scripts/

Eu quero um script para executar scripts/, compactar arquivos que correspondem results.*.logem files/um arquivo tar compactado em archives/.

Estou tentando o seguinte comando:

tar czfC ../archives/archive.tar.gz ../files results.*.log

Mas eu entendo

tar: results.*.log: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

Enquanto

tar czfC ../archives/archive.tar.gz ../files results.a.log

funciona como esperado. Além disso

tar czf ../archives/archive.tar.gz ../files/results.*.log

funciona da maneira que eu gostaria, exceto que adiciona o prefixo files/ao arquivo e também emite um aviso:

tar: Removing leading `../' from member names

Portanto, minha conclusão é que o targlobbing não funciona corretamente ao usar a -Copção. Algum conselho sobre como eu faço isso funcionar de uma maneira simples?

Yuval
fonte

Respostas:

3

Escreva da maneira mais portátil:

(cd ../files && tar cf - results.*.log) | 
  gzip -9 > ../archives/archive.tar.gz
Stéphane Chazelas
fonte
O glob ainda será interpretado no diretório atual, antes que cdaconteça.
vonbrand
1
@ vonbrand, não, é claro que não. &&é como ;ou nova linha, ele separa dois comandos. É como dizer que, após a execução cd, qualquer glob expandiria arquivos no diretório anterior.
Stéphane Chazelas
Você está certo. Nunca se termina de aprender.
vonbrand
5

Não há "piche de alcatrão", o globbing é feito pela concha. E o shell não tem idéia do que tar -C somedirfará seu trabalho somedir; quaisquer globs são expandidos no diretório atual.

vonbrand
fonte
De fato, se results.a.logexiste no diretório a partir do qual o script é executado, ele funciona. Mas não entendo por que isso acontece, pois -Csignifica diretório de mudança, portanto, o diretório atual deve ser o único results.a.log. Não posso aceitar sua resposta porque você não oferece uma solução.
Yuval
2
O shell assume o comando, expande os globs no diretório atual, fabrica os argumentos a partir dos itens acima e inicia o tarprograma, que altera o diretório muito mais tarde. Não é possível "resolver" o seu problema, desculpe. A única saída é ir para o diretório em que você deseja enviar, ou fazer uma busca no diretório e salvar seus resultados em um arquivo ou variável.
vonbrand
1

Você pode deixar findo globbing e omitir a opção 'change directory' tarremovendo o files/prefixo antes de criar o tarfile.

A --no-recursionopção para taré opcional, pois nenhum diretório será arquivado.

cd base/scripts

# gnutar
# printf '%s\000' ../files/results.*.log |  # find alternative
find ../files -maxdepth 1 -type f -name "results.*.log" -print0 | 
   gnutar --transform="s|^\.\{0,1\}\.\{0,1\}/\{0,1\}files/||" -cf - --null --no-recursion -T - | 
   gzip -9 > ../archives/archive.tar.gz
gnutar -tf ../archives/archive.tar.gz | nl
gnutar -xzf ../archives/archive.tar.gz

# bsdtar
find ../files -maxdepth 1 -type f -name "results.*.log" -print0 | 
   bsdtar -s "|^\.\{0,1\}\.\{0,1\}/\{0,1\}files/||" -cf - --null --no-recursion -T - | 
   gzip -9 > ../archives/archive.tar.gz
bsdtar -tf ../archives/archive.tar.gz | nl
bsdtar -xzf ../archives/archive.tar.gz
phron
fonte
0

Eu finalmente usei

tar czfC ../archives/archive.tar.gz ../files `find ../files/results.*.log -printf "%f\n"`
Yuval
fonte
Embora isso possa funcionar para você, é uma maneira bastante complexa de fazer isso. Além disso, ele não funcionará com nomes de arquivos contendo caracteres especiais, como espaço em branco. Use um dos métodos sãos que foram propostos nas respostas.
Gilles 'SO- stop be evil' -
0

A maneira de fazer isso é escrever algo como o seguinte:

#!/bin/sh

cd ../files
tar zcf ../archives/archive.tar.gz results.*.log
cd ../scripts
vonbrand
fonte
0

Não é o alcatrão que faz o globbing, é a concha. Você está primeiro dizendo ao shell para fazer globbing, depois dizendo ao tar para alterar os diretórios. Como o tar está recebendo uma lista de nomes de arquivos em relação aos diretórios originais, isso não funciona.

A solução mais fácil, de longe, é permitir que o shell altere o diretório. Interativamente:

cd ../files
tar czf ../archives/archive.tar.gz  results.*.log
cd -

Em um script:

(
  cd ../files &&
    tar czf ../archives/archive.tar.gz  results.*.log
)

ou

(
  cd ../files &&
    tar czf -  results.*.log
) >../archives/archive.tar.gz
Gilles 'SO- parar de ser mau'
fonte