criando archive usando tar, incluindo todos os 'arquivos de ponto', mas excluindo todos os subdiretórios e / wo estrutura de diretórios

18

Quero fazer backup de todos os 'dotfiles' (fe .zshrc) no meu diretório inicial com tar , mas excluindo a estrutura de diretórios e todos os subdiretórios.

Eu tentei várias vezes com comandos diferentes, mas o melhor que consegui foi um arquivo que também incluía os diretórios ocultos $HOME.

#!/bin/zsh
BACKUPFILE=dotfile_backup.tar.gz
tar --create --file=$HOME/$BACKUPFILE --auto-compress --no-recursion --exclude=. --exclude=.. --exclude=*/ --directory=$HOME .*

Também pensei em usar finde canalizar o resultado para alcatrão, mas sem sorte. Alguém sabe como realizar essa tarefa - aparentemente fácil -?

PS: Na maioria das vezes, quando estou usando o tar para criar um arquivo, tenho que pensar no xkcd comic:

xkcd 1168 :)

klingt.net
fonte
A resposta do sim funciona, mas se alguém tiver um regex que corresponda apenas aos arquivos ocultos, poste-o!
Klingt.net
11
Certamente isso seria melhor alcançado com seu shell. Eu entendo que zsh tem globs que selecionar apenas arquivos - *(.)- e eu acho que exclui .e ..de .*por padrão (e que não iria ser pego por .*(.)qualquer maneira, uma vez que seleciona apenas os arquivos). Eu não uso o zsh, então não tenho certeza o suficiente para transformar isso em uma resposta.
evilsoup

Respostas:

14

Você pode usar este comando para fazer backup de todos os seus dotfiles ( .<something>) no seu $HOMEdiretório:

$ cd ~
$ find . -maxdepth 1 -type f -name ".*" -exec tar zcvf dotfiles.tar.gz {} +

regex usando apenas tar?

Método 1

Eu pesquisei bastante isso e vim vazio. O fator limitante seria que, ao tarexecutar suas exclusões, a barra final ( /) que aparece nos diretórios não faz parte da equação quando o tar está executando sua correspondência de padrões.

Aqui está um exemplo:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*/'} .*
.qalculate/
.qt/
.qterm/
.qtoctave/
.RapidSVN
.RData
.Rhistory

Essa variante inclui uma exclusão de .*/e você pode ver, com a opção detalhada ativada para tar -v, que esses diretórios estão passando por essa exclusão.

método # 2

Eu pensei que talvez os interruptores --no-wildcards-match-slashou --wildcards-match-slashrelaxassem a ganância do .*/mas isso também não teve efeito.

Tirar a barra da exclusão, .*também não era uma opção, pois isso diria tarpara excluir todos os arquivos de ponto e diretórios de ponto:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --exclude={'.','..','.*'} .*
$

método # 3 (Feio!)

Portanto, a única outra alternativa que posso conceber é fornecer uma lista de arquivos tar. Algo assim:

$ tar -v --create --file=do.tar.gz --auto-compress --no-recursion --wildcards-match-slash --exclude={'.','..','.*/'} $(ls -aF | grep -E "^\..*[^/]$")
.RapidSVN
.RData
.Rhistory

Essa abordagem tem problemas se o número de arquivos exceder a quantidade máxima de espaço para a passagem de argumentos para um comando seria um problema flagrante. A outra é que é feia e excessivamente complexa.

então o que aprendemos?

Não parece haver uma maneira direta e elegante de realizar isso usando tarexpressões regulares. Portanto, quanto ao comentário de @ terdon, find ... | tar ...é realmente a maneira mais apropriada de fazer isso.

slm
fonte
Eu realmente queria fazê-lo com regex, mas eu deveria ter sabido que ele não vai funcionar dessa maneira :)
klingt.net
@ klingt.net - deve ser possível, estou procurando agora.
Slm
@ klingt.net Por que você prefere a maneira mais complicada? Usando regexvocê provavelmente precisará escapar do ponto inicial e terá problemas para ignorar .e ... Estou certo de que é possível, como o slm provavelmente demonstrará, mas não vejo por que valeria a pena.
terdon
11
@ klingt.net - tudo o que o findcomando encontra é passado como argumento tar. O {}diz onde você quer esses resultados para ir no correspondente -execcomando. O +diz para adicionar quantos resultados de findcomo se encaixam na linha de comando e chamar tarapenas um par de vezes, em vez de cada vez que um resultado é encontrado.
Slm
11
@ klingt.net - não há como fazer isso usando regexe tarporque não há como isolar os diretórios de ponto ( .blah/). O Tar não usa a barra à direita ao excluir.
Slm
4

Esse tipo de controle sobre os arquivos correspondentes está fora da zona de conforto do alcatrão. Suas regras para arquivos correspondentes são limitadas a correspondências simples sobre nomes.

find é uma maneira, mas como você tem o zsh, é mais fácil:

tar -cf "$HOME/$BACKUPFILE" --auto-compress .*(.)

Entre .parênteses no final da expressão curinga é um qualificador global que diz "corresponder apenas aos arquivos regulares".

Links simbólicos para arquivos regulares não são correspondentes. Se você mudar para .*(-.), eles serão incluídos, mas o arquivo não terminará no arquivo morto, a menos que também esteja incluído. Se você deseja substituir o link simbólico por seus destinos, faça isso .*(-.:A):Aadiciona o modificador de expansão do histórico que resolve todos os links simbólicos a um caminho que não usa links simbólicos.

Gilles 'SO- parar de ser mau'
fonte
3

Essa resposta é baseada no slm, mas também mostrarei como incluir diretórios começando com .

Para compactar arquivos de ponto no diretório inicial:

$ cd
$ find . -maxdepth 1 -type f -name ".?*" -exec tar czfv dotfiles.tgz {} +

Para incluir diretórios:

$ find . -maxdepth 1 -name ".?*" -exec tar czfv dotfiles.tgz {} +

O ?é opcional no primeiro comando, mas não no segundo, caso contrário, findincluirá o .diretório (atual).

sudoman
fonte
1

A respeito:

tar -C $HOME -cvzf dotfiles.tgz .
anonimato
fonte