Tarar um diretório, mas não armazene caminhos absolutos completos no arquivo morto

277

Eu tenho o seguinte comando na parte de um script de shell de backup:

tar -cjf site1.bz2 /var/www/site1/

Quando listo o conteúdo do arquivo, recebo:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

Mas eu gostaria de remover a parte /var/www/site1dos nomes de diretório e arquivo dentro do arquivo morto, para simplificar a extração e evitar a estrutura inútil de diretório constante. Nunca se sabe, caso eu extraísse sites de backup em um local em que os dados da web não estivessem armazenados /var/www.

Para o exemplo acima, eu gostaria de ter:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

Portanto, quando extraio, os arquivos são extraídos no diretório atual e não preciso mover os arquivos extraídos posteriormente, para que as estruturas de subdiretórios sejam preservadas.

Já existem muitas perguntas sobre tar e backup em stackoverflowe em outros lugares da Web, mas a maioria delas pede a remoção de toda a estrutura de subdiretórios (achatamento), ou apenas adiciona ou remove os nomes iniciais / (eu não não sei o que muda exatamente ao extrair), mas não mais.

Depois de ler algumas das soluções encontradas aqui e ali, bem como o manual, tentei:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

Mas nenhum deles funcionou do jeito que eu quero. Alguns não fazem nada, outros não arquivam mais subdiretórios.

Está dentro de um script de shell de backup lançado por um Cron, então eu não sei bem, qual usuário o executa, qual é o caminho e o diretório atual; portanto, sempre é necessário escrever o caminho absoluto para tudo e prefere não alterar o diretório atual para evitar quebrar algo mais no script (porque ele não apenas faz backup de sites, mas também de bancos de dados, envia tudo isso para FTP etc.)

Como conseguir isso?

Acabei de entender como a opção -C funciona?

QuentinC
fonte
Bem, -Capenas significa "alterar diretório", enquanto a substituição de um caminho (ou prefixo) pode ser feita apenas por --transform. rif. superuser.com/questions/595510/prepend-prefix-in-tar/595512, você pode simplesmente -C (alterar o diretório) e --transformar: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. ``
Daniele Cruciani
Essa é uma pergunta muito boa e, infelizmente, nenhuma das respostas até hoje é satisfatória. Ainda estamos sabendo de alguma pessoa sábia como poderíamos extrair apenas o arquivo style.css (exemplo acima) no diretório atual sem nenhuma referência ao local original ou à árvore de diretórios? Não quero desorganizar meu diretório atual com uma nova estrutura de árvore indesejada. Parece uma grave falha de tarball que é ignorada há anos.
elmclose 11/06

Respostas:

383
tar -cjf site1.tar.bz2 -C /var/www/site1 .

No exemplo acima, o tar mudará para o diretório /var/www/site1antes de fazer o seu trabalho porque a opção -C /var/www/site1foi dada.

De man tar:

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR
Lars Brinkhoff
fonte
152
Não perca o ponto no final, que é importante ;-)
Freedom_Ben
9
e se você também quiser selecionar os arquivos para backup com base em um curinga? -C / var / www / site1 * .dat não funciona :(
Andy Lorenz
16
O ponto diz tarpara arquivar tudo no diretório atual. E -Cdefine o diretório atual.
Lars Brinkhoff
21
Isso funciona muito bem. Acho útil preservar o nome do diretório (não apenas o caminho completo), então fiz o seguinte: tar -czvf site1.tar.gz -C /var/www/ site1(Observe o espaço, ainda estou usando o -C, para cd no diretório pai e especificando o diretório para tar em vez de ponto)
jorfus
9
Eu recebo um ponto inicial no caminho do alcatrão, por exemplo, ./folderscomo isso pode ser removido?
precisa saber é o seguinte
39

A opção -Cfunciona; apenas para esclarecimentos, vou postar 2 exemplos:

  1. criação de um tarball sem o caminho completo: caminho completo /home/testuser/workspace/project/application.ware o que queremos é project/application.waro seguinte:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project

    Nota: existe um espaço entre workspacee project; O tar substituirá o caminho completo por just project.

  2. extração de tarball com alteração do caminho de destino (padrão para ., ie diretório atual)

    tar -xvf output_filename.tar -C /home/deploy/

    tarextrairá o tarball com base no caminho especificado e preservará o caminho da criação; no nosso exemplo, o arquivo application.warserá extraído para /home/deploy/project/application.war.

    /home/deploy: dado em extrato
    project: dado em criação de tarball

Nota: se você deseja colocar o tarball criado em um diretório de destino, basta adicionar o caminho de destino antes do nome do tarball. por exemplo:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project
Grizli
fonte
1
como adicionar curinga para seleção de arquivo no último exemplo?
Siva
O problema com curingas é que o shell expande-los para os nomes de arquivos correspondentes e que tar não expandi-los se eles são citados ...
van den Berg Gert
Eu tentei isso no Ubuntu 18.04 e sem sorte. Não tenho certeza do que estou perdendo. Meu stdout está exibindo corretamente quando eu empacotá-lo, mas quando eu o descompacto, ele ainda tem o caminho completo
sdc 25/02
14

Parece que a -Copção up to tar v2.8.3 não funciona de maneira consistente em todas as plataformas (SOs). -CDiz-se que a opção adiciona um diretório ao arquivo, mas no Mac e Ubuntu ele adiciona um prefixo de caminho absoluto no arquivo tar.gz gerado.

tar target_path/file.tar.gz -C source_path/source_dir

Portanto, a solução consistente e robusta é cdentrar em source_path (diretório pai de source_dir) e executar

tar target_path/file.tar.gz source_dir

ou

tar -cf target_path/file.tar.gz source_dir

no seu script. Isso removerá o prefixo do caminho absoluto na estrutura de diretórios do arquivo tar.gz gerado.

Chinthaka Senanayaka
fonte
1
Uso da opção -C DID remover prefixos de caminho absoluto dentro do arquivo tar.gz gerado no Fedora 29. É sua resposta específica a algum sistema?
EL_DON 8/02/19
@EL_DON: Eu não testei a opção -C no Fedora, mas, idealmente, o software de aplicativo tar deve funcionar consistentemente em todas as plataformas, a menos que seja um bug no aplicativo tar. -C, testei no Mac 10.8 e Mac 10.13 e Ubuntu (versão que não me lembro). Mas, a partir do tar v2.8.3, o comando foi alterado para tar -cf target_path / file.tar.gz source_dir e ainda se você adicionar a opção -C, ele não removerá o prefixo do caminho absoluto no arquivo tar.gz gerado.
Chinthaka Senanayaka 24/02/19
Eu testei novamente em um sistema centOS. Depois de criar todos os caminhos no exemplo e executar o comando (com o -cvfadd depois tar), acho que o arquivo tar.gz resultante não possui caminhos absolutos dentro dele, o que é consistente com várias outras respostas. Se você acha que o tar está desatualizado ou desatualizado nos dois sistemas que usei para teste, vincule-o a alguma documentação que suporte sua resposta. Eu acho que a -Copção altera o diretório antes de executar (como em outras respostas). Quando o omito, o tar tenta adicionar lixo eletrônico ./, incluindo caminhos a partir de ./.
EL_DON
Eu usei este documento: linux.die.net/man/1/tar Sim, o documento diz que -C faria a mudança de caminho, mas no meu Mac 10.13 não está funcionando. isso pode ser um comportamento inconsistente do aplicativo tar. Isso significa que isso é um bug. Se você estiver escrevendo um script de shell para executar em todas as plataformas unix, é melhor estar seguro com o código em execução que funcionará em todos os sistemas operacionais.
Chinthaka Senanayaka 28/02/19
Sua resposta não diz que pode haver um erro, e a solução mais robusta para compatibilidade entre plataformas é a cdprimeira. Sua resposta diz que a ferramenta funciona da maneira oposta de como os documentos dizem que funciona e como funciona no meu sistema, por isso é uma resposta errada. Você poderia consertá-lo facilmente.
EL_DON 28/02/19
7

O comando a seguir criará um diretório raiz "." e coloque todos os arquivos do diretório especificado nele.

tar -cjf site1.tar.bz2 -C /var/www/site1 .

Se você deseja colocar todos os arquivos na raiz do arquivo tar, @chinthaka está certo. Apenas entre no diretório e faça:

tar -cjf target_path/file.tar.gz *

Isso colocará todos os arquivos no cwd no arquivo tar como arquivos raiz.

WLatif
fonte
1
Usar o * não salva nenhum arquivo ou pasta "oculta". (fyi, utilizando em conjunto com -C * falhar, o reservatório se expande a pasta corrente, não o dir -C)
Xen2050
1

O uso do "point" leva à criação de uma pasta chamada "point" (no Ubuntu 16).

tar -tf site1.bz2 -C /var/www/site1/ .

Eu lidei com isso com mais detalhes e preparei um exemplo. Gravação em várias linhas, além de uma exceção.

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/
Sergey Asachev
fonte
Por que você está chamando isso de "ponto"? É apenas ., que é o diretório atual. No contexto da tar.gzestrutura da, isso é apenas o nível básico / raiz / superior, certo?
EL_DON 8/02/19
Veja o instantâneo para obter detalhes da imagem . Meu caminho é mais correto de usar, é minha opinião.
Sergey Asachev 13/02/19
0

Se você deseja arquivar um subdiretório e aparar o caminho do subdiretório, este comando será útil:

tar -cjf site1.bz2 -C /var/www/ site1
Hirurg103
fonte