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


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

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

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

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.


2
find $(INP_PATH} -type f -ls |grep -v "${INP_PATH}/.*/"

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.