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í.
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.
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.xmlfile2.xmlfile3.xml, y luego el shell llama lscon la lista resultante de argumentos file1.xmlfile2.xmlfile3.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":
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.
Los shell ejecuta el comando findcon la lista especificada de argumentos: ., -name, *.xml.
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:
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.
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.
La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, *.xml.
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:
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.
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.
La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, file1.xml, file2.xml, file3.xml.
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:
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.
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.
La cáscara se ejecuta el comando findcon la lista resultante de argumentos, que es ., -name, file.xml.
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í.)
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.
man find
: Tenga en cuenta que debe citar patrones de forma habitual, de lo contrario, el shell expandirá los caracteres comodín en ellos.Respuestas:
De lo contrario, se expande su concha
*.xml
aXYZ.xml
, y el comando que se ejecuta es en realidadLa 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í.fuente
bash
, no defind
.Debes citar tu argumento así:
para que se pase a buscar en lugar de ser expandido por el shell, luego se pasa a buscar como la versión expandida.
fuente
*.xml
no coincide con nada en el directorio actual, se pasa literalmente, por lo que funciona en el otro caso. Muy útil respuesta.Los comodines se expanden por el shell, no por el comando.
find
es 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*.xml
a la lista de archivos coincidentes, por ejemplofile1.xml
file2.xml
file3.xml
, y luego el shell llamals
con la lista resultante de argumentosfile1.xml
file2.xml
file3.xml
. Es por eso que ve la misma lista de nombres de archivoecho *.xml
, aunqueecho
no sabe nada sobre los archivos y no le importa si sus argumentos son nombres de archivos.Cuando corres
find . -name "*.xml"
:find
,.
,-name
,*.xml
en el que el*
se cita. Como*
se cita, es un personaje ordinario en lo que respecta al shell.find
con la lista especificada de argumentos:.
,-name
,*.xml
.find
busca archivos cuyo nombre coincida con el patrón*.xml
en cualquier directorio bajo el directorio actual.Cuando ejecuta
find . -name *.xml
y no hay archivos que coincidan*.xml
:find
,.
,-name
,*.xml
en el que el*
se que no se negocian.*.xml
contiene 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.find
con la lista resultante de argumentos, que es.
,-name
,*.xml
.find
busca archivos cuyo nombre coincida con el patrón*.xml
en cualquier directorio bajo el directorio actual.Cuando ejecuta
find . -name *.xml
y el directorio actual contienefile1.xml
,file2.xml
yfile3.xml
:find
,.
,-name
,*.xml
en el que el*
se que no se negocian.*.xml
contiene un carácter comodín sin comillas, el shell realiza la generación del nombre de archivo:*.xml
se reemplaza por la lista de nombres de archivo coincidentes.find
con la lista resultante de argumentos, que es.
,-name
,file1.xml
,file2.xml
,file3.xml
.find
se queja de un error de sintaxis cuando llegafile2.xml
.Cuando ejecuta
find . -name *.xml
y el directorio actual contiene un solo archivo coincidentefile.xml
:find
,.
,-name
,*.xml
en el que el*
se que no se negocian.*.xml
contiene un carácter comodín sin comillas, el shell realiza la generación del nombre de archivo:*.xml
se reemplaza por la lista de nombres de archivo coincidentes.find
con la lista resultante de argumentos, que es.
,-name
,file.xml
.find
ve un comando perfectamente válido, pero probablemente no sea lo que pretendía:find
se le dice que busque los archivos llamadosfile.xml
en 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í.)
fuente
Esto funciona en Solaris 10:
find /directory-to-search/* -prune -name "*gz"
fuente
.xml
.Por favor, inténtalo:
fuente
*
siempre debe citarse o escaparon a pasarlo a encontrar.