Excluir um subdiretório usando find

115

Eu tenho uma estrutura de diretório como esta

data
|___
   |
   abc
    |____incoming
   def
    |____incoming
    |____processed
   123
    |___incoming
   456
    |___incoming
    |___processed

Existe uma subpasta de entrada em todas as pastas dentro do diretório de dados. Quero obter todos os arquivos de todas as pastas e subpastas, exceto os diretórios def / entrando e 456 / entrando. Eu tentei com o seguinte comando

 find /home/feeds/data -type d \( -name 'def/incoming' -o -name '456/incoming' -o -name arkona \) -prune -o -name '*.*' -print

mas não está funcionando como esperado.

Ravi

Ravi
fonte
3
Este não é um bom conselho, mas vai te tirar de muitas situações rápido e sujo: canalize isso grep -v somethingpara excluir tudo o que você não quer
Miquel
Isso responde sua pergunta? Como excluir um diretório em find. comando
imz - Ivan Zakharyaschev

Respostas:

206

Isso funciona:

find /home/feeds/data -type f -not -path "*def/incoming*" -not -path "*456/incoming*"

Explicação:

  • find /home/feeds/data: começa a encontrar recursivamente a partir do caminho especificado
  • -type f: encontrar apenas arquivos
  • -not -path "*def/incoming*": não inclui nada com def/incomingcomo parte de seu caminho
  • -not -path "*456/incoming*": não inclui nada com 456/incomingcomo parte de seu caminho
Sampson-Chen
fonte
recebendo um erro "find: bad option -not find: path-list predicate-list"
Ravi
@Ravi você está usando o bash shell? Acabei de testar isso no meu terminal e funciona para mim. Tente copiar e colar a solução, se você fez modificações em seu script.
sampson-chen
Está funcionando, mas está listando os diretórios, não os arquivos nesses diretórios.
Ravi de
1
-pathcorresponde a toda a string, então se você estiver fazendo find ., então suas -pathstrings precisam ser./path/to/directory/*
Heath Borders
1
FYI -not -pathdefinitivamente funcionará neste exemplo, mas findainda está iterando na estrutura de diretório e usando ciclos de cpu para iterar sobre todos esses diretórios / arquivos. para evitar a finditeração nesses diretórios / arquivos (talvez haja milhões de arquivos lá), então você precisa usar -prune(a -pruneopção é difícil de usar, no entanto).
Trevor Boyd Smith
9

Apenas para fins de documentação: talvez seja necessário cavar mais fundo, pois há muitas constelações search'n'skip (como eu tive). Pode acabar prunesendo seu amigo, mas -not -pathnão fará o que você espera.

Portanto, este é um exemplo valioso de 15 exemplos de localização que excluem diretórios:

http://www.theunixschool.com/2012/07/find-command-15-examples-to-exclude.html

Para vincular à pergunta inicial, excluir finalmente funcionou para mim assim:

find . -regex-type posix-extended -regex ".*def/incoming.*|.*456/incoming.*" -prune -o -print 

Então, se você deseja encontrar um arquivo e ainda excluir os caminhos, basta adicionar | grep myFile.txt.

Pode depender também da sua versão de localização. Entendo:

$ find -version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX
peter_the_oak
fonte
5

-namecorresponde apenas ao nome do arquivo, não ao caminho inteiro. Em -pathvez disso, você deseja usar para as partes em que está removendo os diretórios, como def/incoming.

Brian Campbell
fonte
2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"
Vishal Pathak
fonte
7
Algumas explicações podem tornar esta resposta muito melhor.
Cris Luengo
Obrigado por este trecho de código, que pode fornecer alguma ajuda limitada de curto prazo. Uma explicação adequada melhoraria muito seu valor a longo prazo, mostrando por que essa é uma boa solução para o problema, e a tornaria mais útil para futuros leitores com outras questões semelhantes. Edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez
Shawn C.
1
Nota: Este truque não funciona se for usado find ... -print0em conjunto com um posteriorxargs -0
phs