【问题标题】:Stop shell wildcard character expansion?停止 shell 通配符扩展?
【发布时间】:2012-07-12 11:21:03
【问题描述】:

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

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

foo *

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

【问题讨论】:

    标签: bash wildcard


    【解决方案1】:

    没有。扩展发生在命令实际运行之前。
    您只能在运行命令之前或通过引用星号来禁用 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
    

    【讨论】:

    • 另外,如果没有什么可扩展的,就没有扩展。即有一个空的pwdecho * 只是*
    • @sam 这实际上取决于您的选项是如何设置的。 From tldp: "如果没有找到匹配的文件名,并且 shell 选项 nullglob 被禁用,则单词保持不变。如果设置了 nullglob 选项,但没有找到匹配项,则删除该单词。"
    • 谢谢,我应该认为那只是观察,而不是任何理解。
    • @c00kiemon5ter 如何撤消set -f ?是unset -f吗?
    • @NamGVU set +f
    【解决方案2】:

    虽然命令本身确实不能关闭通配,但用户可以告诉 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 shell:

    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 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 的需要。

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

    【讨论】:

    • 这应该是公认的答案,因为它证明确实可以做 OP 想要的事情。对于 bash 中的一些更好的方法,此链接记录了各种选项:blog.edwards-research.com/2011/05/preventing-globbing
    • @geira:有时会在发布更好的答案之前接受答案。我相信这可能是其中一种情况。我也相信用户最有用的答案标记最终会排在第一位。注意:我将您的输入添加到我的答案中。
    • @geira,OP希望编译后的程序与shell通信;回答可以将 shell 配置为在逐个命令的基础上按需要运行是一个有用的答案,我自己会接受这个答案,但我确实看到了不同意它是否完全正确的空间。
    • 可以完成并不意味着它应该完成。让 shell 的行为偏离用户对选择命令的合理期望,这听起来令人惊讶且最终是不可取的。
    • @tripleee:曾经有一段时间人们期待继电器和真空管。预计会在纸板卡和纸带上打孔。人们拿着计算尺而不是计算器和手机。我想这对你来说是可取的。那些时候我并没有太在意。我很高兴看到接下来会发生什么。
    【解决方案3】:

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

       set -o noglob
    

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

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

    foo "*"
    

    【讨论】:

    • setopt 似乎是 zsh 特定的命令。正如另一位海报所说,对于 bash,您使用 set -o noglob 禁用通配符扩展。
    • 现已修正。谢谢
    【解决方案4】:

    注意:如果没有与掩码匹配的名称,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 nullglobshopt -s failglob,这种行为将会改变(以两种截然不同的方式)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多