find: o prune não ignora o caminho especificado

9

Preciso excluir .git da minha pesquisa de find . Para conseguir isso, estou usando a opção -path ./.git -prune :

$ find . -path ./.git -prune -o \( -type f -o -type l -o -type d \) | grep '.git'
./.git

No entanto, mesmo que isso ignore o conteúdo do diretório .git, ele lista o próprio diretório. Funciona quando eu adiciono -path ./.git -prune -o -print -a

find . -path ./.git -prune -o -print -a \( -type f -o -type l -o -type d \) | grep '.git'

Por que isso é necessário? Eu pensei que ambos os comandos devem ter a mesma saída. A segunda sintaxe é bem feia.

    
por Martin Vegter 18.01.2014 / 17:57

3 respostas

2

A página man para find dá:

-prune True; if the file is a directory, do not  descend  into  it.  If
      -depth  is  given,  false;  no  effect.  Because -delete implies
      -depth, you cannot usefully use -prune and -delete together.

Portanto, no primeiro exemplo, não é assim que -path ./.git -prune é falso e, portanto, a ação padrão ( -print ) não seria chamada, portanto a linha é impressa.

    
por 19.01.2014 / 10:21
13

Eu estava confuso sobre por que os diretórios removidos estavam sendo impressos pelo comando find também e alguns outros detalhes intrincados de como o -prune funcionava, mas foi capaz de descobrir isso com alguns exemplos.

Para executar os exemplos abaixo, crie os seguintes diretórios e arquivos.

mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3

Agora use find para procurar diretórios chamados aa. Não tem problema aqui.

$ find . -type d -name aa
./aa

Procure por todos os diretórios que não sejam aa e obtemos o diretório atual. e ./bb que também faz sentido.

$ find . -type d ! -name aa
.
./bb

Até aí tudo bem, mas quando usamos -prune, find retorna o diretório que estamos removendo, o que inicialmente me confundiu porque eu esperava que ele retornasse todos os outros diretórios e não aquele que estava sendo podado.

$ find . -type d -name aa -prune
./aa

O motivo pelo qual ele retorna o diretório que está sendo limpo não é explicado na seção -prune das páginas man, conforme indicado na resposta de Timo , mas na seção EXPRESSIONS :

"If the expression contains no actions other than -prune, -print is performed on all files for which the expression is true."

O que significa que, como a expressão corresponde ao nome do diretório aa , a expressão será avaliada como true e será impressa porque o find na verdade adiciona uma impressão no final de todo o comando. No entanto, você não adicionará um -print se propositadamente adicionar a ação -o -print ao final:

find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3

Aqui, o comando "Localizar" NÃO adiciona mais uma impressão implícita e, portanto, o diretório que estamos removendo aa não será impresso.

Então, finalmente, se adicionarmos uma cláusula que procura por arquivos com um padrão de nome de arquivo 'file *' depois do -o então você tem que colocar um -print no final dessa segunda cláusula assim:

find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3

A razão pela qual isso funciona é a mesma: se você não colocar uma -print na segunda cláusula, então, como não há nenhuma ação diferente da ação -prune, o find adicionará -print automaticamente no THE END do comando fazendo com que a cláusula -prune imprima o diretório limpo:

find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3

Em geral, você precisa colocar o comando -print na segunda cláusula. Se você colocá-lo no meio como fez o pôster original, ele não funcionará corretamente porque os arquivos que estão sendo removidos serão impressos imediatamente e a segunda cláusula não terá a chance de escolher os arquivos desejados:

find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3

Então, infelizmente, o pôster original errou o comando colocando o -print no lugar errado. Pode ter funcionado para o seu caso específico, mas não funciona no caso geral.

Existem milhares de pessoas que têm dificuldades em entender como o -prune funciona. stackoverflow.com/questions/4210042/exclude-directory-from-find-command/ 15736463 # 15736463 A página find man deve ser atualizada para evitar a confusão mundial sem fim sobre este comando.

    
por 11.06.2015 / 21:02
0

da página man ,

To ignore a whole directory tree, use -prune rather than checking every file in the tree. For example, to skip the directory 'src/emacs' and all files and directories under it, and print the names of the other files found, do something like this:

find . -path ./src/emacs -prune -o -print

Então, você pode usar:

find . -path ./.git -prune -o -print

Isso não listará o diretório .git .

para especificar um nome de arquivo, você pode fazer assim:

find . -path ./.git -prune , -name filename

Por favor, observe o operador , comma.

    
por 18.11.2017 / 17:23

Tags