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.