Escreva de maneira mais portátil:
(cd ../files && tar cf - results.*.log) |
gzip -9 > ../archives/archive.tar.gz
Eu tenho a seguinte estrutura de diretórios:
base/
files/
archives/
scripts/
Eu quero que um script seja executado a partir de scripts/
, comprima arquivos que correspondam a results.*.log
em files/
em um arquivo tar compactado com gzip em archives/
.
Estou tentando o seguinte comando:
tar czfC ../archives/archive.tar.gz ../files results.*.log
Mas eu recebo
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. Também
tar czf ../archives/archive.tar.gz ../files/results.*.log
funciona do jeito 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 tar
globbing não funciona corretamente ao usar a opção -C
. Algum conselho sobre como eu faço isso funcionar de uma maneira simples?
Não há "tar globbing", o globbing é feito pelo shell. E o shell não tem idéia de que tar -C somedir
fará seu trabalho em somedir
, todos os globs serão expandidos no diretório atual.
Você pode deixar find
fazer o globbing e omitir a opção 'alterar diretório' para tar
removendo o prefixo files/
antes de criar o arquivo tar.
A opção --no-recursion
para tar
é opcional, pois nenhum diretório será arquivado.
cd base/scripts
# gnutar
# printf '%scd base/scripts
# gnutar
# printf '%s%pre%0' ../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
0' ../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
Eu finalmente usei
tar czfC ../archives/archive.tar.gz ../files 'find ../files/results.*.log -printf "%f\n"'
A maneira de fazer isso é escrever algo como o seguinte:
#!/bin/sh
cd ../files
tar zcf ../archives/archive.tar.gz results.*.log
cd ../scripts
Não é o alcatrão que faz o globbing, é o shell. Primeiro você está dizendo ao shell para fazer globbing, então dizendo ao tar para mudar 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 é 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