108

编译后的命令行程序有什么方法可以告诉 bash 或 csh 它不希望扩展其参数中的任何通配符?

例如,可能需要一个 shell 命令,例如:

foo *

简单地返回该字符的数字 ASCII 值。

4

4 回答 4

148

不会。扩展发生在命令实际运行之前。
您只能在运行命令之前或通过引用星号来禁用 glob。

$ # 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
于 2012-07-12T16:36:22.253 回答
69

虽然命令本身确实不能关闭通配,但用户可以告诉 Unix shell 不要通配特定命令。这通常通过编辑 shell 的配置文件来完成。假设foo可以在命令路径中找到该命令,则需要将以下内容添加到相应的配置文件中:

对于 sh、bash 和 ksh shell:

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

对于 csh 和 tcsh shell:

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

对于 zsh 外壳:

alias foo='noglob foo'

不必使用命令路径。假设命令 foo 存储在目录 ~/bin 中,那么上面的内容将变为:

对于 sh、bash 和 ksh shell:

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

对于 csh 和 tcsh shell:

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

对于 zsh 外壳:

alias foo='noglob ~/bin/foo'

以上所有内容均使用 Apple 的 OSX 10.9.2 进行了测试。注意:复制上述代码时,请注意删除任何空格。它们可能很重要。

更新:

用户geira指出,在 bash shell 的情况下

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

可以替换为

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

这消除了对函数 foo 的需要。

用于创建此文档的一些网站:

于 2014-04-08T18:13:43.627 回答
8

扩展是在程序运行之前由 shell 执行的。您的程序不知道是否发生了扩展。

   set -o noglob

将关闭调用 shell 中的扩展,但您必须在调用程序之前执行此操作。

另一种方法是引用您的论点,例如

foo "*"
于 2012-07-12T16:33:51.680 回答
2

注意:如果没有匹配掩码的名称,bash 会按原样传递参数,而不进行扩展!

证明(pa.py 是一个非常简单的脚本,它只打印它的参数):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
 $ ./pa.py *.cpp
['./pa.py', '*.cpp']
于 2014-09-24T11:52:15.387 回答