Como restringir a localização do Linux pelo prefixo?

1

Eu tenho um diretório A com um grande número de subdiretórios e arquivos e quero obter uma lista de todos os arquivos chamados foo que estão dentro de um diretório em A que corresponde a *bar . Por exemplo:

  • Sim: ./goldbar/fiz/baz/foo
  • Sim: ./leadbar/foo
  • Não: ./candy/figbar/foo

Eu tenho algumas restrições adicionais:

  • Eu não devo descer em diretórios que não correspondam ao *bar (essa é uma otimização necessária, pois levaria muito tempo para varrê-los)
  • Não posso permitir que o shell faça a expansão glob porque ele retorna a muitos resultados: (por exemplo, find *bar -type f -name foo falha)

Acho que a -path flag me daria os resultados de que preciso, mas não sei se se encaixa na primeira das restrições acima.

Edit: Suponha que existem diretórios n * 10k em A que correspondem a *bar . ou seja, qualquer coisa que tente construir um comando com todos eles (ao invés de manipular cada um em tern) falhará.

    
por BCS 19.04.2011 / 17:31

5 respostas

2

Não tenho certeza de como -path lidará com o requisito "não desça a diretórios que não correspondam a *bar " e estou com preguiça de criar um ambiente para descobrir.
Eu sei que o seguinte irá funcionar em praticamente qualquer plataforma * nix:

for dir in 'ls -1 | grep bar'; do
   find $dir -type f -name foo
done

O weaseling adicional do bit ls / grep pode ser necessário se você tiver arquivos simples, sockets, etc. em seu diretório de nível superior, ou se quiser revisar suas condições um pouco.

    
por 19.04.2011 / 17:38
2

Se você está procurando uma solução puramente com find , então

find . \( -depth 1 -type d \! -name "*bar" \) -prune -o \( -depth +1 \! -type d -name foo \) -print

deve fazer o truque.

    
por 19.04.2011 / 18:45
2

Tente isso - não tenho certeza de quão rápido será.

find -maxdepth 1 -type d -name '*bar' -exec find {} -name foo \;

OBSERVE que isso não funciona para o Solaris 10, já que ele não tem -maxdepth

    
por 19.04.2011 / 19:05
1

Que tal uma versão de regex:

find -regex './[^/]*bar/.*/?foo$'

EDIT: Tweaked com um mais limpo e terminando a linha (então você não está combinando fooble, foogasm, etc ...)

    
por 19.04.2011 / 19:56
1

Eu verifiquei com strace e -path por si só não evita a incursão não unida em diretórios não correspondentes. Isso deve fazer o trabalho, no entanto:

find . \( -name '.' \) -print -o \( ! -path '*directory_pattern*' \) -prune -o -name '*file_pattern*' -print

Os \( e \) s não são realmente necessários neste caso específico, mas eles adicionam legibilidade e provavelmente seriam necessários se você usasse expressões mais complexas. Verificado com strace e parece funcionar, espero que ajude.

    
por 19.04.2011 / 17:52

Tags