有什么方法可以让已编译的命令行程序告诉bash或csh它不想扩展其参数中的任何通配符?
例如,可能需要像这样的shell命令:
foo *
简单地返回该字符的数字ASCII值。
Answers:
否。扩展发生在命令实际运行之前。
您只能在运行命令或引用星号之前禁用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
set -f
?是unset -f
吗
set +f
虽然命令本身确实不能关闭globing,但用户有可能告诉Unix shell不要glob特定命令。通常,这是通过编辑Shell的配置文件来完成的。假设foo
可以在命令路径中找到该命令,则需要将以下内容添加到适当的配置文件中:
对于sh,bash和ksh外壳:
alias foo='set -f;foo';foo(){ command foo "$@";set +f;}
对于csh和tcsh shell:
alias foo 'set noglob;\foo \!*;unset noglob'
对于zsh shell:
alias foo='noglob foo'
不必使用命令路径。假设命令foo存储在目录〜/ bin中,则上面的内容将变为:
对于sh,bash和ksh外壳:
alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}
对于csh和tcsh shell:
alias foo 'set noglob;$home/bin/foo \!*;unset noglob'
对于zsh shell:
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的需要。
一些用于创建此文档的网站:
扩展在运行程序之前由外壳执行。您的程序不知道是否发生了扩展。
set -o noglob
会在调用外壳程序中关闭扩展功能,但是您必须在调用程序之前执行此操作。
另一种方法是引用您的论据,例如
foo "*"
set -o noglob
可以禁用通配符扩展。
当心:如果没有与掩码匹配的名称,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']
set -o nullglob
或shopt -s failglob
,此行为将发生变化(以两种非常不同的方式)。
pwd
,echo *
只是*