Como faço para impedir que uma descoberta desça nos diretórios encontrados?

24

Estou querendo encontrar todos os diretórios com uma sequência específica para que eu possa encontrar outra vez os arquivos contidos nele.

Então eu não quero perder tempo com ./my-search-term/dir/my-search-termetc.

Como posso parar de repetir quando encontrei o primeiro diretório de termos de pesquisa?

Stephen
fonte
3
Você já tentou encontrar com -prune? Na página do manual: "se o arquivo for um diretório, não desça para ele. Se -deth for fornecido, false; sem efeito. Como -delete implica em -thth, você não poderá usar -une e -delete juntos."
Laebshade
1
@laebshade Por que você não coloca isso em uma resposta?
Jw013
@ jw013 Não tive tempo para fornecer uma resposta mais aprofundada naquele momento.
Laebshade 19/11/11

Respostas:

17

A -pruneação findnão recursa no diretório Você pode combiná-lo com outra ação, como -exec(a ordem -prunee -execnão importa, desde que -pruneseja executada de qualquer maneira).

find . -name my-search-term -prune -exec find {} … \;

Observe que aninhar finddentro de um find -execpode ser um pouco problemático: você não pode usar -execno interior find, porque o terminador seria visto como um terminador pelo externo find. Você pode contornar isso invocando um shell, mas cuidado com a citação.

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +
Gilles 'SO- parar de ser mau'
fonte
Os parênteses em seu primeiro comando são necessários? -pruneretorna true e pode ser colocado antes do -exec.
rozcietrzewiacz
@rozcietrzewiacz Não, eles não são necessários. Hábito de ter um -olá dentro, eu acho. E acho que colocar -pruneantes -execé mais legível.
Gilles 'SO- stop be evil'
Obrigado, não usei a -pruneopção antes.
haridsv
No meu caso de uso, este comando: mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \;dá o erro: find: ./x1: No such file or directory. A solução é adicionar -pruneno final do findcomando.
haridsv
(1) Algumas versões de findexpandem {}mesmo quando aparecem como uma substring de um argumento para -exec. Essa versão do findsufocará em seu segundo comando, porque o comando {}interno find(no comando shell) será substituído pelo nome do diretório encontrado no externo find. Você pode corrigir isso dizendo find . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; , ou seja, usando "{"}, no qual o shell se transformará {}. ... (continua)
Scott
6

- soluções simples -

Se você quiser findpular o conteúdo do diretório encontrado, mas continuar pesquisando em outros diretórios, use -prunecomo @laebshade sugerido. O comando completo deve se parecer com

 find . -type d -name somename -prune -exec ...

Por outro lado, se você deseja interromperfind completamente a pesquisa e depois de encontrar o primeiro diretório correspondente, o que você está procurando é -quit(disponível desde a versão 4.2.3do GNU find). Este é um pouco mais complicado de usar, porque findsai imediatamente - portanto -quitdeve ser colocado no final do comando:

find . -type d -name somename -exec ... -quit

Para que isso funcione conforme o esperado, é preciso garantir que os -execretornos sejam verdadeiros (em outras palavras, um status zero ). Se você deseja que o status de saída -execseja ignorado, para que -quitsempre funcione, é necessário um pequeno truque:

find . -type d -name somename \( -exec ... -o -true \) -quit

ou

find . -type d -name somename \( -exec ... -o -quit \)

ou

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- alguma explicação -

O mais importante sobre como findfunciona é que todas as ações ("testes") são tratadas como predicados lógicos interpretados da esquerda para a direita. Portanto, a última ação (por exemplo -quit) só será executada se a parte anterior inteira não retornar falsa . Por padrão, todos os testes são associados ao lógico "AND", a -oopção altera a junção para "OR".

Um elemento complicado -oé que você findpode "otimizar" seu comando e não executar a -execparte se você digitar apenas

find . -type d -name somename -exec ... -o -quit

Para lidar com isso, você pode forçar finda avaliar todos os predicados com "OR", colocando-os entre parênteses.

rozcietrzewiacz
fonte