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.