encontrar no recursivo cuando el archivo en la parte superior

8

Imagina un árbol fuente. Hay archivos xml en todas partes.

Pero como hay un XYZ.xml en la raíz de este árbol, no encontrará mis archivos xml.

find -iname *.xml

devoluciones

./XYZ.xml

en vez de

./XYZ.xml
./a/b/c/bob.xml
./b/d/top.xml
Olivier Toupin
fuente
1
De man find: Tenga en cuenta que debe citar patrones de forma habitual, de lo contrario, el shell expandirá los caracteres comodín en ellos.
artdanil

Respuestas:

18
find -iname '*.xml'

De lo contrario, se expande su concha *.xmla XYZ.xml, y el comando que se ejecuta es en realidad

find -iname XYZ.xml

La razón por la que funciona si no hay archivos XML en el directorio actual es que los shells generalmente dejan comodines sin expandir si no coinciden con nada. En general, cada vez que quiera comodines para ser expandido en un programa que no sea el shell (por ejemplo, por find, tar, scp, etc.) que necesita para citarlos por lo que la cáscara no tratará de ampliarlos en sí.

cjm
fuente
1
Gracias, eso es muy simple, pero me he estado preguntando cómo solucionarlo durante meses. Encontré eso realmente extraño, y que es un comportamiento muy inconsistente, pero ahora lo entiendo ya que no es encontrar, sino culpa de Bash.
Olivier Toupin
2
No es la "culpa" de Bash per-se sino la suya por no citar los comodines que quería pasar como argumentos. Esto se aplica a todos los programas que aceptan entrada de shell. El caparazón los expande como globos a menos que se citen o escapen.
Caleb
1
Supongo que Olivier lo quiso decir en el sentido, que es una cuestión de bash, no de find.
Usuario desconocido
6

Debes citar tu argumento así:

find ./ -name '*.xml'

para que se pase a buscar en lugar de ser expandido por el shell, luego se pasa a buscar como la versión expandida.

Caleb
fuente
1
Ok, entonces si *.xmlno coincide con nada en el directorio actual, se pasa literalmente, por lo que funciona en el otro caso. Muy útil respuesta.
Eric Wilson
1

Los comodines se expanden por el shell, no por el comando. findes uno de los pocos comandos que realiza la coincidencia de comodines que es similar al shell, en su propio tiempo.

Cuando ejecuta ls *.xml, primero el shell se expande *.xmla la lista de archivos coincidentes, por ejemplo file1.xml file2.xml file3.xml, y luego el shell llama lscon la lista resultante de argumentos file1.xml file2.xml file3.xml. Es por eso que ve la misma lista de nombres de archivo echo *.xml, aunque echono sabe nada sobre los archivos y no le importa si sus argumentos son nombres de archivos.

Cuando corres find . -name "*.xml":

  1. El shell analiza la línea de comando para reconocer caracteres especiales y dividirlo en palabras y puntuación. Aquí sólo hay una lista de palabras find, ., -name, *.xmlen el que el *se cita. Como *se cita, es un personaje ordinario en lo que respecta al shell.
  2. Los shell ejecuta el comando findcon la lista especificada de argumentos: ., -name, *.xml.
  3. findbusca archivos cuyo nombre coincida con el patrón *.xmlen cualquier directorio bajo el directorio actual.

Cuando ejecuta find . -name *.xmly no hay archivos que coincidan *.xml:

  1. El shell analiza la línea de comando para reconocer caracteres especiales y dividirlo en palabras y puntuación. Aquí sólo hay una lista de palabras find, ., -name, *.xmlen el que el *se que no se negocian.
  2. Como la palabra *.xmlcontiene un carácter comodín sin comillas, el shell realiza la generación del nombre de archivo. Como no hay nombres de archivo coincidentes, el patrón permanece sin expandir.
  3. La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, *.xml.
  4. findbusca archivos cuyo nombre coincida con el patrón *.xmlen cualquier directorio bajo el directorio actual.

Cuando ejecuta find . -name *.xmly el directorio actual contiene file1.xml, file2.xmly file3.xml:

  1. El shell analiza la línea de comando para reconocer caracteres especiales y dividirlo en palabras y puntuación. Aquí sólo hay una lista de palabras find, ., -name, *.xmlen el que el *se que no se negocian.
  2. Como la palabra *.xmlcontiene un carácter comodín sin comillas, el shell realiza la generación del nombre de archivo: *.xmlse reemplaza por la lista de nombres de archivo coincidentes.
  3. La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, file1.xml, file2.xml, file3.xml.
  4. findse queja de un error de sintaxis cuando llega file2.xml.

Cuando ejecuta find . -name *.xmly el directorio actual contiene un solo archivo coincidente file.xml:

  1. El shell analiza la línea de comando para reconocer caracteres especiales y dividirlo en palabras y puntuación. Aquí sólo hay una lista de palabras find, ., -name, *.xmlen el que el *se que no se negocian.
  2. Como la palabra *.xmlcontiene un carácter comodín sin comillas, el shell realiza la generación del nombre de archivo: *.xmlse reemplaza por la lista de nombres de archivo coincidentes.
  3. La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, file.xml.
  4. findve un comando perfectamente válido, pero probablemente no sea lo que pretendía: findse le dice que busque los archivos llamados file.xmlen cualquier directorio, no que busque ninguna coincidencia de archivos *.xml.

(La evaluación y expansión de Shell tiene muchas otras características. Solo mencioné las que son relevantes aquí).

(Lo que describo es el comportamiento predeterminado de los shells más comunes: sh, bash, dash, ksh, ... Algunos shells se pueden configurar para mostrar un error en lugar de ejecutar un comando con comodines sin expandir, o para expandir comodines no coincidentes a un vacío lista. Ninguno de esos ayudaría aquí.)

Gilles 'SO- deja de ser malvado'
fuente
-1

Esto funciona en Solaris 10:

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

usuario32445
fuente
Esto no buscaría nombres que terminen en .xml.
Kusalananda
-2

Por favor, inténtalo:

find ./ -name *.xml
Tok
fuente
Acabo de probar eso, el mismo resultado.
Eric Wilson
Lo he intentado y funciona. En GNU bash 4.2.8
bbaja42
3
Esto no funciona cuando el glob coincide con algo en el directorio actual. ¡Es la sintaxis incorrecta! El *siempre debe citarse o escaparon a pasarlo a encontrar.
Caleb