我的环境
OSX 10.11.6
zsh 5.0.8 (x86_64-apple-darwin15.0)
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Mono C# compiler version 4.0.5.0
test.cs中
class Test {
public static void Main() {
System.Console.WriteLine("hello, world");
}
}
test.sh
#! /bin/bash
mcs -recurse:*.cs
我可以使用./test.sh来编译test.cs
但如果我将test.sh更改为
#! /bin/zsh
mcs -recurse:*.cs
错误显示
./test.sh:3: no matches found: -recurse:*.cs
那么,为什么我不能使用zsh?
答案 0 :(得分:2)
zsh
正试图将该单词中的*
扩展为文件glob,失败并抛出错误。
bash
执行相同的操作,但默认情况下,它只是忽略了全局失败并保持单词完整(所以mcs
看到了它所期望的参数)。
将shopt -s failglob
添加到脚本顶部(bash
),它也会失败。
引用*
参数中的mcs
以避免这种情况。
mcs -recurse:'*.cs'
答案 1 :(得分:2)
因为字符串-recurse:*.cs
包含不带引号的*
,所以大多数shell会尝试将其视为glob模式并将其扩展为一个或多个匹配的文件名。
zsh
中的默认行为是将没有匹配的模式视为错误,而不是将模式视为文字字符串。如果您启用bash
选项,则可以在failglob
中看到相同的行为。
$ echo foo*
foo*
$ shopt -s failglob
$ echo foo*
bash: no match: foo*
在zsh
中,引用模式:
#! /bin/zsh
mcs -recurse:"*.cs"
关闭NOMATCH
选项,
#! /bin/zsh
setopt NO_NOMATCH
mcs -recurse:*.cs
或使用zsh命令修饰符:
#! /bin/zsh
noglob mcs -recurse:*.cs
答案 2 :(得分:1)
在您的命令mcs -recurse:*.cs
中,*
旨在作为参数的文字部分传递给mcs
,但它对所有常见的Unix shell也有意义({{ 1}},bash
,zsh
和其他)作为路径名扩展的通配符。因此,如果工作目录中有一个名为tcsh
的文件,您的命令可能会让您感到惊讶。
贝壳中出现了差异。没有文件与给定模式匹配时的默认行为。默认情况下,-recurse:oops.cs
会回到猜测你的意思是bash
是文字,这实际上就是你的意思。另一方面,*
表现出由于未能匹配模式而导致失败的更传统行为。通过启用zsh
选项,bash
也可以被诱导表现出这种行为。
最好的解决方案是通过引用参数来解决歧义,或至少转义其中的failglob
。 *
和bash
都应该处理此版本,没有任何特殊选项:
zsh