tar: adiciona todos os arquivos e diretórios do diretório atual INCLUINDO .svn e assim por diante


91

Eu tento tar.gz um diretório e uso

tar -czf workspace.tar.gz *

O tar resultante inclui .svndiretórios em subdiretórios mas NÃO no diretório atual (visto que *é expandido para apenas os arquivos 'visíveis' antes de ser passado para o tar

Eu tentei

tar -czf workspace.tar.gz .em vez disso, estou recebendo um erro porque '.' mudou durante a leitura:

tar: ./workspace.tar.gz: file changed as we read it

Existe um truque para *corresponder a todos os arquivos (incluindo com prefixo de ponto) em um diretório?

(usando bash no Linux SLES-11 (2.6.27.19)


5
Talvez esta pergunta pertença ao superusuário?
Peter Jaric

Respostas:


78

Não crie o arquivo tar no diretório que você está empacotando:

tar -czf /tmp/workspace.tar.gz .

faz o truque, exceto que irá extrair os arquivos de todo o diretório atual quando você descompactar. Melhor fazer:

cd ..
tar -czf workspace.tar.gz workspace

ou, se você não sabe o nome do diretório em que estava:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(Isso pressupõe que você não seguiu links simbólicos para chegar onde está e que o shell não tenta adivinhar você saltando para trás através de um link simbólico - bashnão é confiável a este respeito. Se você tiver que se preocupar com isso, uso cd -P ..para fazer um diretório de mudança física. Estúpido que não seja o comportamento padrão na minha opinião - confuso, pelo menos, para aqueles para quem cd ..nunca teve qualquer significado alternativo.)


Um comentário na discussão diz:

Preciso excluir o diretório superior e [...] preciso colocar o tar no diretório base.

A primeira parte do comentário não faz muito sentido - se o arquivo tar contém o diretório atual, ele não será criado quando você extrair o arquivo desse arquivo porque, por definição, o diretório atual já existe (exceto em circunstâncias muito estranhas )

A segunda parte do comentário pode ser tratada de duas maneiras:

  1. Ou: crie o arquivo em outro lugar - /tmpé um local possível - e mova-o de volta para o local original depois de concluído.
  2. Ou: se você estiver usando GNU Tar, use a --exclude=workspace.tar.gzopção. A string após o =é um padrão - o exemplo é o padrão mais simples - uma correspondência exata. Você pode precisar especificar --exclude=./workspace.tar.gzse está trabalhando no diretório atual, contrariando as recomendações; você pode precisar especificar --exclude=workspace/workspace.tar.gzse está trabalhando em um nível acima, conforme sugerido. Se você tiver vários arquivos tar para excluir, use ' *', como em --exclude=./*.gz.

1
Boa resposta, mas tenho uma situação em que sou forçado a executar este comando dentro do diretório que deve ser compactado. Não tenho permissões suficientes para executá-lo fora.
Hexodus

Um lugar perfeito para embalar é / tmp com certeza.
Andre Fellows

46

Se você realmente não deseja incluir o diretório principal no tarball (e isso geralmente é uma má ideia):

tar czf workspace.tar.gz -C /path/to/workspace .

Estou precisando excluir o diretório principal e colocando o tar no diretório base.
Micha

@Micha faz um script bash para arquivar e copiar o arquivo depois
Fedir RYKHTIK

2
Você está perdendo o - em -czf, eu acho.
UpTheCreek

10
man tar: O primeiro argumento para tar deve ser uma função; uma das letras Acdrtuxou um dos nomes longos das funções. Uma letra de função não precisa ser prefixada com- e pode ser combinada com outras opções de uma letra.
rkhayrov

4
Ainda não funciona, ainda tenho o "." como diretório principal em meu tarball
A. Gille

44

Existem algumas etapas a serem seguidas:

  1. Substitua *por .para incluir arquivos ocultos também.
  2. Para criar o arquivo no mesmo diretório, --exclude=workspace.tar.gzpode ser usado para excluir o próprio arquivo.
  3. Para evitar o tar: .: file changed as we read iterro quando o arquivo ainda não foi criado, certifique-se de que ele exista (por exemplo, usando touch), para que --exclude corresponda ao nome do arquivo. (Não corresponde ao arquivo não existe)

Combinado esses resultados no seguinte script:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Eu li todas as respostas e comentários e esta é a melhor maneira de criar tarball no mesmo diretório. Com essa resposta, também entendi porque esse erro acontece.
Szymon Sadło

Se você quiser ver o progresso enquanto ele está comprimindo seu arquivo tar, você pode adicionar um sinalizador adicional para --verbose, assim: -czvf.
Mastrianni

19

no diretório deseja compactar (diretório atual) tente isto:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Mas agora ele reclama que o arquivo "." alterado durante a leitura. Posso ter certeza de que todos os arquivos foram incluídos?
Jaan

1
Isso exclui todos os .gzarquivos do diretório.
omerfarukdogan

12

Você pode incluir os diretórios ocultos voltando a um diretório e fazendo:

cd ..
tar czf workspace.tar.gz workspace

Supondo que o diretório que você deseja criar gzip seja chamado de espaço de trabalho


E isso evita o problema de alteração de arquivo também.
Jonathan Leffler

Não funciona quando o usuário não tem permissão de gravação na pasta pai.
Joachim Wagner

Exatamente @JoachimWagner!
p01ymath

1
@JoachimWagner. Se você não tiver permissão de gravação, mude para:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Tive que tirar -antes do czfpara fazer funcionar. Caso contrário, eu estava recebendo Cannot stat: No such file or directoryuma mensagem de erro.
Phemelo Khetho

6

Você pode corrigir o .formulário usando --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Atualização: adicionei uma correção para o comentário do OP.

tar -czf workspace.tar.gz .

irá realmente alterar o diretório atual, mas por que não colocar o arquivo em outro lugar?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

O arquivo será processado posteriormente e deve estar no espaço de trabalho - é um pouco feio, mas é apenas necessário (a coisa toda é apenas uma solução alternativa ...)
Micha

OK, vou adicionar uma correção para isso :)
Peter Jaric

E se você precisar executar isto repetidamente, adicione 'rm workspace.tar.gz' antes da linha tar.
Peter Jaric

Se você quiser tar uma unidade inteira, em que mesma unidade, parece que você não tem muitas opções.
BeeOnRope

4

Na verdade, o problema está nas opções de compactação. O truque é canalizar o resultado do tar para um compressor em vez de usar as opções embutidas. A propósito, isso também pode fornecer uma melhor compactação, já que você pode definir opções de compactação extras.

Alcatrão mínimo:

tar --exclude=*.tar* -cf workspace.tar .

Pipe para um compressor de sua escolha. Este exemplo é detalhado e usa xz com compactação máxima:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

A solução foi testada no Ubuntu 14.04 e Cygwin no Windows 7. É uma resposta do wiki da comunidade, então fique à vontade para editar se você encontrar um erro.


Obrigado! Salvou minha vida
Steven

2

O problema com a maioria das soluções fornecidas aqui é que o tar contém ./no início de cada entrada. Portanto, isso resulta em ter .diretório ao abri-lo por meio do compressor GUI. Então o que acabei fazendo é:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Se você já tem um my.tar.gzdiretório atual, pode querer executar o grep:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Esteja ciente de que xargs tem certo limite (consulte Recursos xargs --show-limits). Portanto, esta solução não funcionaria se você estiver tentando criar um pacote que possui muitas entradas (diretórios e arquivos) em um diretório que você está tentando tar.


1

Boa pergunta. No ZSH, você pode usar o modificador globbing (D), que significa "dotfiles". Comparar:

ls $HOME/*

e

ls $HOME/*(D)

Isso exclui corretamente as entradas de diretório especiais .e ... No Bash, você pode usar .*para incluir os dotfiles explicitamente:

ls $HOME/* $HOME/.*

Mas isso inclui .e ..também, então não é o que você estava procurando. Tenho certeza de que também há uma maneira de *combinar dotfiles no bash.


No bash, use .??*para corresponder a todos os arquivos de ponto, não .e ... Isso não obtém arquivos de ponto de caractere único (como .a). Para obtê-los também, use o mais complicado .[^.]*.
Scott Minster

1

Outra solução, presumindo que o número de itens na pasta não seja grande:

tar -czf workspace.tar.gz `ls -A`

( ls -Aimprime arquivos normais e ocultos, mas não "." e ".." como ls -afaz.)


0
tar -czf workspace.tar.gz .??* *

A especificação .??*incluirá arquivos e diretórios "dot" com pelo menos 2 caracteres após o ponto. A desvantagem é que não incluirá arquivos / diretórios com um único caractere após o ponto, como .a, se houver algum.


0

Se o espaço em disco não for um problema, isso também pode ser uma coisa muito fácil de fazer:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

Eu mesmo tive uma situação semelhante. Eu acho que é melhor criar o tar em outro lugar e então usar -C para informar ao tar o diretório base para os arquivos compactados. Exemplo:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

Desta forma, não há necessidade de excluir seu próprio tarfile. Conforme observado em outros comentários, -A listará os arquivos ocultos.


0

10 anos depois, você tem uma alternativa ao tar, ilustrado com Git 2.30 (Q1 2021), que usa " git archive" ( man ) para produzir o tarball de lançamento em vez de tar.
(Você não precisa do Git 2.30 para aplicar essa alternativa)

Consulte o compromisso 4813277 (11 de outubro de 2020) e o compromisso 93e7031 (10 de outubro de 2020) de René Scharfe ( rscharfe) .
(Incorporado por Junio ​​C Hamano - gitster- no commit 63e5273 , 27 de outubro de 2020)

Makefile: use git init / add / commit / archive para dist-doc

Assinado por: René Scharfe

Reduza a dependência de ferramentas externas gerando os arquivos de distribuição para documentação HTML e páginas de manual usando comandos ( man ) em vez de tar. Isso dá às entradas do arquivo os mesmos metadados que os do arquivo dist para binários.git

Então, em vez de:

tar cf ../archive.tar .

Você pode fazer usando apenas Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

Isso foi proposto inicialmente porque, conforme explicado aqui , algumas plataformas exóticas podem ter uma distribuição tar antiga com opções ausentes.


-1

Usar findé provavelmente a maneira mais fácil:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1encontrará todos os arquivos / diretórios / links simbólicos / etc no diretório atual e executará o comando especificado por -exec. O {}no comando significa que a lista de arquivos vai aqui e \+significa que o comando será executado como:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

ao invés de

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J é --xz no manual; combinado com -c é apenas o começo do que um computador chamará de "diversão" :)
Ricalsin

Haha, meu mini-servidor em casa é mais limitado pelo espaço em disco do que pela CPU :) Bom ponto; Vou alterá-lo para usar gzip.
Andrew Gunnerson
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.