¿Detener la expansión de caracteres comodín de Shell?
¿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.
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
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 foo
se 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
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 "*"
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']