En la mayoría de los shells nullglob no es el predeterminado. Eso significa, por ejemplo, que si ejecuta este comando
ls *
en un directorio vacío, expandirá el * glob a un * literal , en lugar de una lista vacía de argumentos. Hay formas de cambiar ese comportamiento, de modo que * en un directorio vacío devolverá una lista vacía de argumentos, lo que parecería más intuitivo.
Entonces, ¿hay alguna razón por la que nullglob está deshabilitado por defecto? Si es así, ¿cuál es ese motivo?
Respuesta aceptada:
El nullglob opción (que por cierto es un zsh invención, solo se agregó años después a bash (2.0 )) no sería ideal en varios casos. Y ls es un buen ejemplo:
ls *.txt
O su equivalente más correcto:
ls -- *.txt
Con nullglob on ejecutaría ls sin argumento que se trata como ls -- . (enumere el directorio actual) si ningún archivo coincide, lo que probablemente sea peor que llamar a ls con un literal *.txt como argumento.
Tendría problemas similares con la mayoría de las utilidades de texto:
grep foo *.txt
Buscaría foo en stdin si no hay txt archivo.
Un valor predeterminado más sensato, y el de csh, tcsh, zsh o fish 2.3+ (y de los primeros shells de Unix) es cancelar el comando por completo si el glob no coincide.
bash (desde la versión 3) tiene un failglob opción para eso (interesante para esta discusión, ya que contrario a ash , AT&T ksh o zsh , bash no admite ámbitos locales para las opciones (aunque eso cambiará en 4.4), esa opción, cuando está habilitada globalmente, rompe algunas cosas como las funciones de finalización de bash).
Tenga en cuenta que csh y tcsh son ligeramente diferentes de zsh , fish o bash -O failglob en casos como:
ls -- *.txt *.html
Donde necesita que todos los globos no coincidan para que se cancele el comando. Por ejemplo, si hay un archivo txt y ningún archivo html, se convierte en:
ls -- file.txt
Puedes obtener ese comportamiento con zsh con setopt cshnullglob aunque una forma más sensata de hacerlo en zsh sería usar un glob como:
ls -- *.(txt|html)
En zsh y ksh93 , también puede aplicar nullglob por globo, que es un enfoque mucho más sensato que modificar una configuración global:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
crearía una matriz vacía si no hay txt archivo en lugar de fallar el comando con un error (o convertirlo en una matriz con un *.txt argumento literal con otros shells).
Versiones de fish antes de 2.3 funcionaría como bash -O nullglob pero da una advertencia cuando es interactivo cuando un globo no tiene coincidencia. Desde 2.3, funciona como zsh a excepción de los globos usados en for , set o count .
Ahora, en la nota de historial, el comportamiento en realidad estaba roto por la concha de Bourne. En versiones anteriores de Unix, el globbing se realizaba a través de /etc/glob ayudante y ese ayudante se comportó como csh :fallaría el comando si ninguno de los globos coincidiera con ningún archivo y, de lo contrario, eliminaría los globos sin coincidencia.
Así que la situación en la que nos encontramos hoy se debe a una mala decisión tomada en el caparazón de Bourne.
Tenga en cuenta que el shell Bourne (y el shell C) vienen con otra característica nueva de Unix:el entorno. Eso significaba una expansión variable (su predecesor solo tenía el $1 , $2 … parámetros posicionales). El shell Bourne también introdujo la sustitución de comandos.
Otra mala decisión de diseño del shell Bourne fue realizar globbing (y división) en la expansión de variables y sustitución de comandos (posiblemente por compatibilidad con versiones anteriores del shell Thompson donde echo $1 todavía invocaría /etc/glob si $1 contenía comodines (era más como una expansión de macro de preprocesador allí, ya que el valor expandido se analizó nuevamente como código de shell)).
Los globos que fallan y no coinciden significarían, por ejemplo, que:
pattern='a.*b'
grep $pattern file
fallaría el comando (a menos que haya algún a.whateverb archivos en el directorio actual). csh (que también realiza globbing sobre la expansión variable) falla el comando en ese caso (y diría que es mejor que dejar un error inactivo allí, incluso si no es tan bueno como no hacer globbing como en zsh ).