achar não recursivo quando o arquivo na parte superior

8

Imagine uma árvore de origem. Existem arquivos xml em todos os lugares.

Mas como existe um XYZ.xml na raiz desta árvore, ele não encontrará meus arquivos xml.

find -iname *.xml

retorna

./XYZ.xml

ao invés de

./XYZ.xml
./a/b/c/bob.xml
./b/d/top.xml
Olivier Toupin
fonte
1
De man find: Observe que você deve citar padrões com toda a certeza; caso contrário, o shell expandirá qualquer caractere curinga neles.
Artdanil

Respostas:

18
find -iname '*.xml'

Caso contrário, seu shell se expandirá *.xmlpara XYZ.xml, e o comando que realmente é executado é

find -iname XYZ.xml

O motivo pelo qual funciona se não houver arquivos XML no diretório atual é que os shells geralmente deixam os curingas não expandidos se não corresponderem a nada. Em geral, qualquer hora que quiser curingas para ser expandida por um programa que não seja o shell (por exemplo, por find, tar, scp, etc.) que você precisa para citá-los para que o shell não vai tentar expandi-los em si.

cjm
fonte
1
Thx, isso é tão simples, mas eu tenho me perguntado como contornar isso há meses. Achei isso muito estranho, e para ser um comportamento muito inconsistente, mas agora eu entendo, pois não é encontrado, mas a culpa do bash.
Olivier Toupin
2
Não é a "falha" do bash em si, mas a sua por não citar caracteres curinga que você deseja passar como argumentos. Isso vale para todos os programas que aceitam entrada do shell. A concha os expande como globs, a menos que sejam citados ou escapados.
Caleb
1
Acho que Olivier quis dizer isso no sentido de que é uma questão de bash, não de find.
usuário desconhecido
6

Você precisa citar seu argumento assim:

find ./ -name '*.xml'

para que seja passado para encontrar em vez de ser expandido pelo shell e depois para encontrar como a versão expandida.

Caleb
fonte
1
Ok, então, se *.xmlnão corresponder a nada no diretório atual, ele será transmitido literalmente, e é por isso que funciona no outro caso. Resposta muito útil.
Eric Wilson
1

Os curingas são expandidos pelo shell, não pelo comando. findé um dos poucos comandos que realiza a correspondência de curingas semelhante ao shell, em seu próprio tempo.

Quando você executa ls *.xml, primeiro o shell se expande *.xmlpara a lista de arquivos correspondentes, por exemplo file1.xml file2.xml file3.xml, e depois o shell chama lscom a lista de argumentos resultante file1.xml file2.xml file3.xml. É por isso que você vê a mesma lista de nomes de arquivos echo *.xml, mesmo que echonão saiba nada sobre arquivos e não se importe se seus argumentos são nomes de arquivos.

Quando você executa find . -name "*.xml":

  1. O shell analisa a linha de comando para reconhecer caracteres especiais e dividi-la em palavras e pontuação. Aqui há apenas uma lista de palavras find, ., -name, *.xmlonde a *é citado. Desde que *é citado, é um caractere comum no que diz respeito ao shell.
  2. O shell executa o comando findcom a lista especificada de argumentos: ., -name, *.xml.
  3. findprocura por arquivos cujo nome corresponda ao padrão *.xmlem qualquer diretório no diretório atual.

Quando você executa find . -name *.xmle não há arquivos correspondentes *.xml:

  1. O shell analisa a linha de comando para reconhecer caracteres especiais e dividi-la em palavras e pontuação. Aqui há apenas uma lista de palavras find, ., -name, *.xmlonde o *não é citado.
  2. Como a palavra *.xmlcontém um caractere curinga sem aspas, o shell executa a geração do nome do arquivo. Como não há nomes de arquivos correspondentes, o padrão permanece não expandido.
  3. O shell executa o comando findcom a lista resultante de argumentos, que é ., -name, *.xml.
  4. findprocura por arquivos cujo nome corresponda ao padrão *.xmlem qualquer diretório no diretório atual.

Quando você executa find . -name *.xmle o diretório atual contém file1.xml, file2.xmle file3.xml:

  1. O shell analisa a linha de comando para reconhecer caracteres especiais e dividi-la em palavras e pontuação. Aqui há apenas uma lista de palavras find, ., -name, *.xmlonde o *não é citado.
  2. Como a palavra *.xmlcontém um caractere curinga sem aspas, o shell executa a geração do nome do arquivo: *.xmlé substituído pela lista de nomes de arquivos correspondentes.
  3. O shell executa o comando findcom a lista resultante de argumentos, que é ., -name, file1.xml, file2.xml, file3.xml.
  4. findreclama de um erro de sintaxe quando é atingido file2.xml.

Quando você executa find . -name *.xmle o diretório atual contém um único arquivo correspondente file.xml:

  1. O shell analisa a linha de comando para reconhecer caracteres especiais e dividi-la em palavras e pontuação. Aqui há apenas uma lista de palavras find, ., -name, *.xmlonde o *não é citado.
  2. Como a palavra *.xmlcontém um caractere curinga sem aspas, o shell executa a geração do nome do arquivo: *.xmlé substituído pela lista de nomes de arquivos correspondentes.
  3. O shell executa o comando findcom a lista resultante de argumentos, que é ., -name, file.xml.
  4. findvê um comando perfeitamente válido, mas provavelmente não é o que você pretendia: findé instruído a procurar arquivos chamados file.xmlem qualquer diretório, a não procurar por nenhum arquivo correspondente *.xml.

(A avaliação e expansão da Shell tem muitos outros recursos. Mencionei apenas os que são relevantes aqui.)

(O que descrevo é o comportamento padrão dos shells mais comuns: sh, bash, dash, ksh, ... Alguns shells podem ser configurados para exibir um erro em vez de executar um comando com curingas não expandidos ou para expandir curingas não correspondentes para um vazio Nenhuma delas ajudaria aqui.)

Gilles 'SO- parar de ser mau'
fonte
-1

Isso funciona no Solaris 10:

find /directory-to-search/* -prune -name "*gz"

user32445
fonte
Isso não procuraria por nomes terminados em .xml.
Kusalananda
-2

Tente por favor:

find ./ -name *.xml
Tok
fonte
Eu apenas tentei isso, mesmo resultado.
Eric Wilson
Eu tentei e funciona. No GNU bash 4.2.8
bbaja42
3
Isso não funciona quando o glob corresponde a qualquer coisa no diretório atual. É a sintaxe errada! O *sempre deve ser citado ou escapado para passá-lo para encontrar.
Caleb