GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué Nullglob no es predeterminado?

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.

Relacionado:Bash + ¿cómo salir del script secundario y del script principal en ambos tiempos?

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 ).


Linux
  1. ¿Por qué Find no acepta '-exec Cp {} Dir +'?

  2. ¿Por qué se bifurca el mecanismo de creación de procesos predeterminado?

  3. Linux:¿por qué no funciona Setuid?

  4. ¿Por qué `exit &` no funciona?

  5. ¿Por qué Lpd no está habilitado de forma predeterminada en la transmisión?

¿Por qué Cd no es un programa?

¿Por qué `clear` no borra toda la pantalla?

file_put_contents no crea un archivo txt

¿Por qué no funciona mi enlace simbólico?

¿Por qué usamos su - y no solo su?

¿Por qué borrar el historial de bash no es suficiente?