filtro em "find" ignorado quando a saída é alimentada no tar

filtro em "find" ignorado quando a saída é alimentada no tar

Eu tenho a seguinte estrutura de diretórios:

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

Quero compactar o diretório "test" excluindo tudo o que está nos subdiretórios (profundidade não predefinida), que inclui as strings "1" ou "2" neles. No bash shell, eu quero usarencontrare alimentar sua saída paraalcatrão. eu primeiro testoencontrar:

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

Saída:

test/
test/3

Ótimo. Então eu combino comalcatrão:

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/

Na verdade, 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 find?

Responder1

Para expandir o que @cuonglm disse, tarpor padrão opera recursivamente. Se você passar um nome de diretório, ele arquivará oconteúdodesse diretório.

Você pode modificar seu findcomando 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 -

Em vez disso, você poderia usar o --no-recursionsinalizador 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/

A --no-recursionbandeira é específica para GNU tar. Se você estiver usando outra coisa, consulte a página de manual apropriada para ver se há um recurso semelhante disponível.

Observe que seu findcomando excluiráarquivosque contêm 1ou 2no caminho, bem como diretórios.

Responder2

Com o GNU tar, você também pode usar a --excludeopção de excluir arquivos com base em nomes.

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

Há também -Xor --exclude-fromwhich pega um arquivo para ler os padrões de exclusão.


Embora as find -not -path "*1*", isso também excluirá arquivos cujos nomes contenham um 1ou 2. Para apenas pulardiretórioscujos nomes correspondem ao padrão, use find -prunee 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 GNU tar e FreeBSD tar possuem --no-recursion)

informação relacionada