filter em “find” ignorado quando a saída é alimentada para tar

6

Eu tenho a seguinte estrutura de diretórios:

test/
test/1/
test/foo2bar/
test/3/

Eu quero compactar o diretório "test", excluindo tudo o que está em subdiretórios (profundidade não predefinida), que incluem strings "1" ou "2" neles. No bash shell, eu quero usar find e alimentar sua saída para tar . Eu primeiro testo encontrar :

find test/ -not -path "*1*" -not -path "*2*"

Saída:

test/
test/3

Ótimo. Então eu combino com tar :

find test/ -not -path "*1*" -not -path "*2*" | tar -czvf test.tar.gz --files-from -

Saída:

test/
test/3/
test/1/
test/foo2bar/
test/3/

De fato, tanto "test / 1" quanto "test / foo2bar" estão presentes no arquivo. Por que esses argumentos foram passados para o tar, se eles não deveriam estar presentes na saída do resultado?

    
por InternazionalIV 07.04.2017 / 13:52

2 respostas

11

Para expandir o que @cuonglm disse, tar , por padrão, opera recursivamente. Se você passar um nome de diretório, ele arquivará o conteúdo desse diretório.

Você pode modificar seu comando find para retornar apenas os nomes dos arquivos, não dos diretórios ...

find test/ -type f -not -path "*1*" -not -path "*2*" |
tar -czvf test.tar.gz --files-from -

Você pode usar o sinal --no-recursion para tar :

find test/ -not -path "*1*" -not -path "*2*" | 
tar -czvf test.tar.gz --no-recursion --files-from - 

O que resulta em:

test/
test/3/

O --no-recursion flag é específico para o GNU tar. Se você estiver usando outra coisa, consulte a man page apropriada para ver se há um recurso semelhante disponível.

Observe que o comando find excluirá arquivos que contêm 1 ou 2 no caminho, bem como nos diretórios.

    
por 07.04.2017 / 14:23
6

Com o GNU tar, você também pode usar a opção --exclude para excluir arquivos baseados em nomes.

$ tar --exclude "*1*" --exclude "*2*" -cvf foo.tar  test/
test/
test/3/

Há também -X ou --exclude-from , que pega um arquivo para ler os padrões de exclusão.

Embora como find -not -path "*1*" , isso também excluirá arquivos cujos nomes contenham 1 ou 2 . Para pular somente diretórios cujos nomes correspondem ao padrão, use find -prune e tar --no-recursion :

$ touch test/3/blah.1
$ find test/ -type d \( -name "*1*" -o -name "*2*" \) -prune -o -print |
   tar cvf test.tar --files-from - --no-recursion
test/
test/3/
test/3/blah.1

(Pelo menos o tar GNU e o tar do FreeBSD tem --no-recursion )

    
por 07.04.2017 / 14:50