Stop shell wildcard character expansion?

2018-12-31 15:23发布

问题:

Is there any way for a compiled command-line program to tell bash or csh that it does not want any wildcard characters in its parameters expanded?

For instance, one might want a shell command like:

foo *

to simply return the numeric ASCII value of that character.

回答1:

No. The expansion takes place before the command is actually run.
You can only disable the glob before running the command or by quoting the star.

$ # quote it
$ foo \'*\'

$ # or escape it
$ foo \\*

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


回答2:

While it is true a command itself can not turn off globbing, it is possible for a user to tell a Unix shell not to glob a particular command. This is usually accomplished by editing a shell\'s configuration files. Assuming the command foo can be found along the command path, the following would need to be added to the appropriate configuration file:

For the sh, bash and ksh shells:

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

For the csh and tcsh shells:

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

For the zsh shell:

alias foo=\'noglob foo\'

The command path does not have to be used. Say the command foo is stored in the directory ~/bin, then the above would become:

For the sh, bash and ksh shells:

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

For the csh and tcsh shells:

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

For the zsh shell:

alias foo=\'noglob ~/bin/foo\'

All of the above was tested using Apple\'s OSX 10.9.2. Note: When copying the above code, be careful about deleting any spaces. They may be significant.

Update:

User geira has pointed out that in the case of a bash shell

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

could be replaced with

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

which eliminates the need for the function foo.

Some web sites used to create this document:

  • Unix shell

  • Pass Command Line Arguments To a Bash Alias Command

  • Csh - The C Shell

  • Bash Builtin Commands

  • Comparison with the Bourne shell and csh startup sequences

  • Alias Loop in csh

  • How to pass command line arguments to a shell alias?

  • Invoking program when a bash function has the same name

  • Special shell variables

  • C Shell Aliases with Command-Line Arguments

  • Preventing Wildcard Expansion / Globbing in Shell Scripts



回答3:

The expansion is performed by the shell before your program is run. Your program has no clue as to whether expansion has occurred or not.

   set -o noglob

will switch off expansion in the invoking shell, but you\'d have to do that before you invoke your program.

The alternative is to quote your arguments e.g.

foo \"*\"


回答4:

Beware: if there are no names matching the mask, bash passes the argument as-is, without expansion!

Proof (pa.py is a very simple script, which just prints its arguments):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
[\'./pa.py\', \'f1.cc\', \'f2.cc\']
 $ ./pa.py *.cpp
[\'./pa.py\', \'*.cpp\']


回答5:

No. A Bourne-style shell always performs globbing when appropriate before executing the command. The user has to quote or escape the arguments to prevent globbing, like foo \\*; the actual program being executed cannot indicate a preference.



标签: bash wildcard