Sintaxe correta para incluir diretórios. * com tar

2

Estou tentando incluir arquivos que correspondem a */*/.thisdirectory/* em um arquivo tar. Qual é a sintaxe correta? Aparentemente, isso não é:

> find .
.
./bar
./bar/.a
./bar/.a/baz
./foo
./foo/.a
> tar --include "*[.]a*" -cvf a.tar .
>
    
por cbmanica 07.05.2016 / 01:45

3 respostas

1

Estou assumindo que você está usando o FreeBSD tar¹, já que esta é a única implementação que conheço com a opção --include .

Quando você passa --include , somente os arquivos incluídos explicitamente são percorridos. Ao construir um arquivo, se um diretório não for atravessado, nem ele nem qualquer um dos seus conteúdos poderão ser incluídos. Como você está com o tar . , mas não incluindo . , o argumento da linha de comando exclusiva não é incluído e você obtém um arquivo vazio.

Para alcançar os diretórios .a , você precisaria incluir todos os diretórios pai. A coisa é, se você fizer isso, então todo o seu conteúdo será incluído também. Você pode usar --exclude para excluí-los, mas precisará de um padrão de exclusão que não exclua os diretórios de pontos que deseja incluir. Neste ponto --include não tem mais uso. A opção --include raramente é útil ao criar um arquivo, é mais útil quando copia parte de um arquivo existente (porque ao fazer isso, não há nenhuma travessia recursiva, apenas uma iteração através da lista de membros do arquivo de entrada). p>

tar --exclude='./*/[!.]*' -cvf a.tar .

Observe que todos os arquivos no diretório de nível superior estão incluídos. Eu não acho que haja uma maneira de incluir apenas os diretórios que terão conteúdos não vazios.

Para obter apenas os diretórios ./*/.* e nada mais (em particular, não seus diretórios pai), você precisa passá-los como argumentos para tar, em vez de permitir que o tar recurse para encontrá-los.

tar -cvf a.tar ./*/.[!.]*/

Remova a barra final para incluir arquivos que não sejam diretórios (ou links simbólicos para diretórios). Adicione ./*/..?*/ para incluir diretórios cujo nome comece com .. se você os tiver.

¹ Possivelmente sob um sistema operacional diferente.

    
por 08.05.2016 / 01:09
1

Se o seu shell é bash, você pode usar a variável GLOBIGNORE para ocultar os diretórios . e .. . Isso também define automaticamente a opção dotglob , portanto, * agora corresponde a arquivos ocultos e não ocultos:

GLOBIGNORE=".:.."
tar czf tarball-with-hidden-files.tgz directory/*

Para expandir isso um pouco: por padrão, * não corresponde a arquivos ocultos (arquivos que começam com . ), que inclui os diretórios atuais ( . ) e parent ( .. ) de qualquer diretório. Se você quiser que um glob (por exemplo, um curinga de linha de comando) combine-os, você precisa definir a opção dotglob , mas isso pode causar realmente coisas ruins se .. corresponder a * e você faz algo como rm -fr /home/olduser/* (porque olduser/.. corresponde, que é /home/ e agora você acabou de fritar os diretórios home de everyones. É aí que GLOBIGNORE entra em ação - ele lista coisas negras de curingas correspondentes. um caso de uso realmente simples:

ghoti@home:~/scratch$ ls -ld ?dotfile
ls: cannot access '?dotfile': No such file or directory
ghoti@home:~/scratch$ touch _dotfile .dotfile
ghoti@home:~/scratch$ ls -ld ?dotfile
-rw-rw-r-- 1 ghoti ghoti 0 May  6 16:58 _dotfile
ghoti@home:~/scratch$ GLOBIGNORE=".:.."
ghoti@home:~/scratch$ ls -ld ?dotfile
-rw-rw-r-- 1 ghoti ghoti 0 May  6 16:58 _dotfile
-rw-rw-r-- 1 ghoti ghoti 0 May  6 16:58 .dotfile

O que isso significa para você? Bem, como no exemplo rápido no topo dessa resposta, depois de definir GLOBIGNORE para ignorar . e .. , você pode usar * para corresponder aos diretórios ocultos, como aqueles que você está tentando arquivar:

tar czf mytarball.tgz directory/*  # this will include things like directory/.hiddenfile

Para apontar isso no seu exemplo específico de um diretório chamado .a :

ghoti@home:~/scratch$ mkdir -p example example/foo/.a example/bar/.a example/foo/_a example/bar/_a
ghoti@home:~/scratch$ touch example/{foo,bar}/{.,_}a/file
ghoti@home:~/scratch$ find example/
example/
example/foo
example/foo/_a
example/foo/_a/file
example/foo/.a
example/foo/.a/file
example/bar
example/bar/_a
example/bar/_a/file
example/bar/.a
example/bar/.a/file
ghoti@home:~/scratch$ GLOBIGNORE=".:.."
ghoti@home:~/scratch$ tar cvzf withdotfiles.tgz example/*/?a
example/bar/_a/
example/bar/_a/file
example/bar/.a/
example/bar/.a/file
example/foo/_a/
example/foo/_a/file
example/foo/.a/
example/foo/.a/file
ghoti@home:~/scratch$ unset GLOBIGNORE
ghoti@home:~/scratch$ tar cvzf withoutdotfiles.tgz example/*/?a
example/bar/_a/
example/bar/_a/file
example/foo/_a/
example/foo/_a/file
    
por 07.05.2016 / 01:50
0

Em vez disso, salte em um cavalo velho aqui, mas, desde que eu não posso encontrar qualquer evidência de alguém apontando a maneira aparentemente "pretendida" que isso deve ser feito com tar:

A questão, como foi notado em outro lugar, é que o tar é bastante literal com "--include", e ele não irá percorrer diretórios foo e bar para encontrar seus arquivos .a, se o --include os filtra primeiro fora.

A pista para o truque de usar o tar como você gostaria de usá-lo / é / incluído na página man, mas é bastante bem ofuscado: --include é "suposto" para ser usado para filtrar arquivos existentes; Além disso, existe um argumento mágico @ - que faz com que o tar trate uma leitura de STDIN como uma leitura de um arquivo existente.

Juntando, você pode usar uma declaração tar promíscua para criar um arquivo de tudo abaixo do diretório atual e colocá-lo no STDOUT. Você então canaliza isso para um tar que vai usar a opção --include, e que lê a partir de STDIN.

No seu caso, parece algo como:

tar -cf - / | tar -cf myfiles.tar --include=" .a" @ -

Soyokaze:test$ ls -lR
total 32
drwxr-xr-x   6 tyler  staff   204 Nov 29 14:24 bar/
drwxr-xr-x   4 tyler  staff   136 Nov 29 14:23 foo/

./bar:
total 0
-rw-r--r--  1 tyler  staff    0 Nov 29 14:23 baa.a
-rw-r--r--  1 tyler  staff    0 Nov 29 14:23 baaa.a
-rw-r--r--  1 tyler  staff    0 Nov 29 14:23 baz
drwxr-xr-x  2 tyler  staff   68 Nov 29 14:24 boos/

./bar/boos:
total 0

./foo:
total 0
-rw-r--r--  1 tyler  staff    0 Nov 29 14:23 baa.a
-rw-r--r--  1 tyler  staff    0 Nov 29 14:23 baz.a

Soyokaze:test$ tar -cf - */ | tar -cf myfiles.tar --include="*.a" @-

Soyokaze:test$ tar -tf myfiles.tar
bar/baa.a
bar/baaa.a
foo/baa.a
foo/baz.a
    
por 29.11.2018 / 20:33

Tags