Estaba jugando con la expansión y noté un comportamiento peculiar. Traté de hacer:
echo ./*.txt
Y no tenía ningún archivo .txt en mi directorio actual. El resultado que obtuve fue:
./*.txt
Solo tengo curiosidad: ¿por qué obtuve esto? Esperaba no obtener ningún resultado.
PD: Cuando tuve un .txt
archivo, la expansión se interpretó correctamente. En otras palabras, digamos que tenía un archivo smthn.txt
, el eco realmente hizo eco current_directory/smthn.txt
.
fuente
shopt -s nullglob
producirá cadenas vacías para patrones no coincidentes yshopt -u nullglob
(configuración estándar) producirá el patrón en sí.Si
nullglob
fuera el valor predeterminado, muchos comandos se comportarían de manera bastante inesperada, porque es (quizás desafortunadamente) común que los comandos traten el caso de cero argumentos de nombre de archivo de una manera cualitativamente diferente que el caso de uno o más argumentos de nombre de archivo.Supongamos que ha habilitado
nullglob
(shopt -s nullglob
) y está en un directorio donde no coinciden los archivos*.txt
. Entonces*.txt
, de hecho, se expandirá a la nada, no a un campo vacío, sino a ningún campo, como esperaba. Pero eso tendría estos resultados:ls *.txt
enumeraría todos los archivos en el directorio actual (excepto los archivos ocultos), porque eso es lo quels
hace cuando no le pasa ningún argumento de nombre de archivo.cat *.txt
leería de la entrada estándar , porque cuandocat
no tiene argumentos de nombre de archivo, es como si ejecutaracat -
. Si se ejecuta de forma interactiva, se queda esperando la entrada. Muchos comandos se comportan de esta manera.cp *.txt dest/
fallaría con el errorcp: missing destination file operand after 'dest/'
. Esto no es un desastre, pero es confuso y bastante diferente del éxito silencioso que probablemente se desea.file *.txt
, y varios otros programas sin comportamiento especial para el caso de argumentos de nombre de archivo cero, aún fallarían con un mensaje de error o uso cuando no se pasa ninguno.printf 'Got file: "%s"\n' *.txt
imprimiría enGot file: ""
lugar de nada.*
,?
y[
que no están destinadas a ser expandidas por el shell produciría con mayor frecuencia resultados obviamente erróneos, pero en formas que podrían ser difíciles de resolver. Por ejemplo, si no comenzó ningún nombre de archivo en el directorio actualgedit
, entoncesapt list gedit*
(dondeapt list 'gedit*'
se pretendía) sería justoapt list
y enumeraría todos los paquetes disponibles.Por lo tanto, es bueno que no obtenga este comportamiento sin solicitarlo. Probablemente la situación práctica más común que en realidad se simplifica
nullglob
esfor f in *.txt
. Ver también esta pregunta (a la que se vincula la respuesta de Sergiy Kolodyazhnyy ).La pregunta más difícil de responder es por qué,
failglob
donde es un error de expansión tener un globo que no coincide con ningún archivo, no es el valor predeterminado en bash. Creo que la respuesta de Sergiy Kolodyazhnyy captura la razón de esto, incluso sin abordarla directamente. Retener globos sin expandir sin producir un error de expansión es (quizás desafortunadamente) el comportamiento estandarizado, y también es un comportamiento tradicional, y por lo tanto esperado. Aunque bash no intenta ser totalmente compatible con POSIX a menos que se invoque con el nombresh
o se le pase la--posix
opción, muchas de sus opciones de diseño incluso cuando no está en modo POSIX siguen a POSIX directamente. Tuvieron que elegir algún comportamiento, y hay desventajas asociadas con ir en contra de las expectativas de los usuarios.Creo que este es el aspecto menos influyente históricamente del asunto, así que lo he guardado para el final ... pero vale la pena mencionar que hay algo un poco conceptualmente extraño en el
nullglob
comportamiento.nullglob
parece elegante al principio porque, sintácticamente , trata el caso de cero archivos coincidentes no de manera diferente al caso de uno, dos o cualquier otro número. Los comandos que ejecutamos, para los cuales los globos se expanden en argumentos, no tienden a tratarlos de la misma manera, como se detalla anteriormente. Pero sintácticamente, esto al menos se siente bien, lo cual creo que es la motivación para su pregunta.Y, sin embargo, hay otra inconsistencia más sutil que
nullglob
no aborda, que en realidad amplifica. El caso de los caracteres de globulo cero ("comodines") se trata de manera profundamente diferente al de uno, dos o cualquier otro número. Por ejemplo, conshopt -s nullglob
, siab?d?f
no coincide con ningún archivo, se elimina; siab?d
no coincide con ningún archivo, se elimina; pero siab
no coincide con ningún archivo (es decir, si no hay ningún archivo cuyo nombre sea exactamenteab
) aún no se elimina. Por supuesto, sería un desastre si se eliminara, ya que podría no estar destinado a referirse a un archivo existente en el directorio actual; Puede que ni siquiera se refiera a un archivo. Pero esto todavía elimina cualquier esperanza de consistencia total.Los tres comportamientos que proporciona bash: el valor predeterminado de tratar los globos que no coinciden con ningún archivo como si no fueran globos y pasarlos sin expandir, el comportamiento que esperaba de tratarlos (si perdona este extraño giro de la frase) como significar todos los cero de los archivos que coinciden (
nullglob
), y el comportamiento seguro de considerarlos errores (failglob
): todos representan enfoques diferentes de la ambigüedad inherente en el shell de no poder saber si alguna palabra en particular está destinada a ser un nombre del archivo. El shell realiza sus expansiones sin saber cómo los comandos particulares que llama con él tratarán sus argumentos.Este es uno de los muchos casos de separación de preocupaciones . En sistemas cuyo diseño sigue la filosofía de Unix, cada parte está destinada a hacer una cosa y hacerlo bien . El shell procesa el texto en comandos y argumentos e invoca esos comandos, la mayoría de los cuales son externos al propio shell. Esto tiende a ser un montón más bonito y más versátil que los sistemas en que los comandos externos son ellos mismos responsables de realizar estas transformaciones (al igual que con los procesadores tradicionales de comando en DOS y Windows). Pero tiene sus inconvenientes ocasionales.
fuente
failglob
. Por lo tanto, no puede ser el valor predeterminado porque no siempre ha sido compatible.La razón principal es porque este es el comportamiento estándar especificado por POSIX , el estándar que cubre el lenguaje de comandos de shell y, entre otras cosas, la coincidencia de patrones (shells como
bash
,dash
shell, el valor predeterminado de Ubuntu/bin/sh
yksh
sigue este estándar). De la sección 2.13.3 Patrones utilizados para la expansión del nombre de archivo :Por supuesto, esto tiene un efecto secundario: coincidencia del nombre de archivo que puede ser literalmente
*.txt
. Lanullglob
opciónbash
yzsh
puede ayudar: si esa opción está habilitada a través deshopt -s nullglob
(y no está habilitada de forma predeterminada, lo que se aplica a esta pregunta), globstar se expandirá a una cadena vacía cuando no se encuentren nombres de archivo coincidentes.ksh93
tiene su propio mecanismo avanzado de coincidencia de patrones que logra el mismo efecto~(N)*.txt
Consulte también ¿Por qué nullglob no es predeterminado?
fuente