En la mayoría de las conchas nullglob
no es el valor predeterminado. Eso significa, por ejemplo, si ejecuta este comando
ls *
en un directorio vacío, expandirá el *
globo a un literal *
, en lugar de a 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á deshabilitada de forma predeterminada? Si es así, ¿cuál es esa razón?
*
es un problema y se expande a todos los archivos existentes ; ¿Cómo es "intuitivo" que haya un caso especial en el que los globos de directorio vacíos se "expandan" a un literal*
?Respuestas:
La
nullglob
opción (que por cierto es unazsh
invención, solo añadida años después abash
(2.0
)) no sería ideal en varios casos. Yls
es un buen ejemplo:O su equivalente más correcto:
Con
nullglob
on se ejecutaríals
sin ningún argumento que se trata comols -- .
(enumere el directorio actual) si no coinciden los archivos, lo que probablemente sea peor que llamarls
con un literal*.txt
como argumento.Tendría problemas similares con la mayoría de las utilidades de texto:
Buscaría
foo
la entrada estándar si no haytxt
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 unafailglob
opción para eso (interesante para esta discusión, ya que al contrario deash
AT&Tksh
ozsh
,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 bash-complete).Tenga en cuenta que csh y tcsh son ligeramente diferentes de
zsh
,fish
obash -O failglob
en casos como: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:
Usted puede conseguir que el comportamiento con
zsh
lasetopt cshnullglob
aunque de una manera más sensata de hacerlo enzsh
sería utilizar un pegote como:En
zsh
yksh93
, también puede aplicar nullglob en función de cada globo, que es un enfoque mucho más sensato que modificar una configuración global:crearía una matriz vacía si no hay un
txt
archivo en lugar de fallar el comando con un error (o convertirlo en una matriz con un*.txt
argumento literal con otros shells).Las versiones
fish
anteriores a la 2.3 funcionarían de la misma manerabash -O nullglob
pero darían una advertencia cuando sean interactivas cuando un globo no tenga coincidencia. Desde 2.3, funciona comozsh
excepto para los globos utilizados enfor
,set
ocount
.Ahora, en la nota del historial, el comportamiento fue realmente roto por el shell Bourne. En versiones anteriores de Unix, el bloqueo se realizaba a través del
/etc/glob
ayudante y ese ayudante se comportaba comocsh
: fallaría el comando si ninguno de los globos coincidía con ningún archivo y, de lo contrario, eliminaría los globos sin coincidencia.Entonces, la situación en la que estamos hoy se debe a una mala decisión tomada en el shell Bourne.
Tenga en cuenta que el shell Bourne (y el shell C) vienen con otra nueva característica de Unix: el entorno. Eso significa la expansión de variables (su predecesor sólo tenía los
$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 el bloqueo (y la división) tras la expansión de las variables y la sustitución de comandos (posiblemente por compatibilidad con el shell Thompson, donde
echo $1
aún se invocaría/etc/glob
si$1
contuviera comodines (era más como una expansión de macro preprocesador). allí, como en el valor expandido, se analizó nuevamente como código shell)).Los globos fallidos que no coinciden significarían, por ejemplo, que:
fallaría el comando (a menos que haya algunos
a.whateverb
archivos en el directorio actual).csh
(que también realiza el bloqueo en la expansión variable) falla el comando en ese caso (y diría que es mejor que dejar un error latente allí, incluso si no es tan bueno como no hacerlo en absolutozsh
).fuente
nullglob
parece romper la finalización de tabulación (presionar la tecla tab no hace nada cuando está habilitado).files=$(shopt -s nullglob;echo *.txt)
xpg_echo
) en variables escalares . Necesitaría algo comoreadarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)
conbash
4.4 o superior o(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmd
con GNUxargs
para que sea utilizable con nombres de archivo arbitrarios. O, aún con bash4.4, use una función auxiliar que uselocal -
(copiada de ceniza 25 años después) para un alcance local de opciones.