¿Detener la expansión de caracteres comodín de Shell?

Resuelto hotpaw2 asked hace 12 años • 4 respuestas

¿Hay alguna forma de que un programa de línea de comandos compilado le diga a bash o csh que no quiere que se expandan ningún carácter comodín en sus parámetros?

Por ejemplo, uno podría querer un comando de shell como:

foo *

para simplemente devolver el valor numérico ASCII de ese carácter.

hotpaw2 avatar Jul 12 '12 23:07 hotpaw2
Aceptado

No. La expansión tiene lugar antes de que se ejecute realmente el comando.
Solo puedes desactivar el globo antes de ejecutar el comando o citando la estrella.

$ # quote it
$ foo '*'

$ # or escape it
$ foo \*

$ # or disable the glob (noglob)
$ set -f
$ foo *

$ # alternative to set -f
$ set -o noglob
$ # undo it by 
$ set +o noglob
c00kiemon5ter avatar Jul 12 '2012 16:07 c00kiemon5ter

Si bien es cierto que un comando en sí no puede desactivar el globbing, es posible que un usuario le indique a un shell Unix que no globbe un comando en particular. Esto generalmente se logra editando los archivos de configuración de un shell. Suponiendo que el comando foose pueda encontrar en la ruta del comando, sería necesario agregar lo siguiente al archivo de configuración apropiado:

Para los shells sh, bash y ksh:

alias foo='set -f;foo';foo(){ command foo "$@";set +f;}

Para los shells csh y tcsh:

alias foo 'set noglob;\foo \!*;unset noglob'

Para el shell zsh:

alias foo='noglob foo'

No es necesario utilizar la ruta del comando. Digamos que el comando foo está almacenado en el directorio ~/bin, entonces lo anterior se convertiría en:

Para los shells sh, bash y ksh:

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

Para los shells csh y tcsh:

alias foo 'set noglob;$home/bin/foo \!*;unset noglob'

Para el shell zsh:

alias foo='noglob ~/bin/foo'

Todo lo anterior se probó utilizando OSX 10.9.2 de Apple. Nota: Al copiar el código anterior, tenga cuidado de eliminar los espacios. Pueden ser significativos.

Actualizar:

El usuario geira ha señalado que en el caso de un shell bash

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

podría ser reemplazado por

reset_expansion(){ CMD="$1";shift;$CMD "$@";set +f;}
alias foo='set -f;reset_expansion ~/bin/foo'

lo que elimina la necesidad de la función foo.

Algunos sitios web utilizados para crear este documento:

  • shell Unix

  • Pasar argumentos de línea de comando a un comando de alias de Bash

  • Csh - El caparazón C

  • Comandos integrados de Bash

  • Comparación con las secuencias de inicio de Bourne shell y csh

  • Bucle de alias en csh

  • ¿Cómo pasar argumentos de línea de comando a un alias de shell?

  • Invocar programa cuando una función bash tiene el mismo nombre

  • Variables de shell especiales

  • Alias ​​de Shell C con argumentos de línea de comandos

  • Prevención de la expansión/globbing de comodines en scripts de Shell

David Anderson avatar Apr 08 '2014 18:04 David Anderson

La expansión la realiza el shell antes de ejecutar el programa. Su programa no tiene idea de si se ha producido una expansión o no.

   set -o noglob

desactivará la expansión en el shell de invocación, pero tendrás que hacerlo antes de invocar tu programa.

La alternativa es citar sus argumentos, por ejemplo.

foo "*"
Brian Agnew avatar Jul 12 '2012 16:07 Brian Agnew

Cuidado: si no hay nombres que coincidan con la máscara, bash pasa el argumento tal como está, ¡sin expansión!

Prueba (pa.py es un script muy simple, que simplemente imprime sus argumentos):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
 $ ./pa.py *.cpp
['./pa.py', '*.cpp']
lesnik avatar Sep 24 '2014 11:09 lesnik