简体   繁体   English

不能使用/ bin / zsh来编译csharp程序,但是/ bin / bash可以

[英]Can not use /bin/zsh to compile a csharp program, but /bin/bash can

My env 我的环境

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 test.cs

class Test {
        public static void Main() {
                System.Console.WriteLine("hello, world");
        }
}

test.sh test.sh

#! /bin/bash

mcs -recurse:*.cs

I can use ./test.sh to compile test.cs 我可以使用./test.sh来编译test.cs

but if I change test.sh to 但是如果我将test.sh更改为

#! /bin/zsh

mcs -recurse:*.cs

error shows 错误显示

./test.sh:3: no matches found: -recurse:*.cs

So, Why I can not use zsh? 那么,为什么我不能使用zsh?

zsh is attempting to expand the * in that word as a file glob, failing, and throwing an error. zsh尝试将该单词中的*扩展为文件glob,失败并引发错误。

bash does the same thing but, by default, it just ignores the globbing failure and keeps the word intact (so mcs sees the argument it expects). bash做同样的事情,但是默认情况下,它只是忽略了globbing失败并保持单词完整(因此mcs看到了它期望的参数)。

Add shopt -s failglob to the top of the script (for bash ) and it will fail also. shopt -s failglob添加到脚本顶部(对于bash ),它也会失败。

Quote the * in the argument to mcs to avoid this. 为了避免这种情况,请在mcs的参数中引用*

mcs -recurse:'*.cs'

Because the string -recurse:*.cs contains an unquoted * , most shells will attempt to treat it as a glob pattern and expand it to one or more matching file names. 因为字符串-recurse:*.cs包含未加引号的* ,所以大多数shell都会尝试将其视为glob模式并将其扩展为一个或多个匹配的文件名。

The default behavior in zsh is to treat a pattern that has no matches as an error, rather than treating the pattern as a literal string. zsh的默认行为是将没有匹配项的模式视为错误,而不是将模式视为文字字符串。 The same behavior can be seen in bash if you enable the failglob option. 如果启用failglob选项,则在bash可以看到相同的行为。

$ echo foo*
foo*
$ shopt -s failglob
$ echo foo*
bash: no match: foo*

In zsh , either quote the pattern: zsh ,要么引用模式:

#! /bin/zsh

mcs -recurse:"*.cs"

turn off the NOMATCH option, 关闭NOMATCH选项,

#! /bin/zsh

setopt NO_NOMATCH
mcs -recurse:*.cs

or use the zsh command modifier: 或使用zsh命令修饰符:

#! /bin/zsh

noglob mcs -recurse:*.cs

In your command mcs -recurse:*.cs , the * is intended to be passed to mcs as a literal part of the argument, but it is also meaningful to all common Unix shells ( bash , zsh , tcsh , and others) as a wildcard for pathname expansion. 在您的命令mcs -recurse:*.cs*旨在作为参数的文字部分传递给mcs ,但对于所有常见的Unix shell( bashzshtcsh和其他),它也有意义。通配符,用于路径名扩展。 As such, your command would probably surprise you if there were a file named -recurse:oops.cs in the working directory. 这样,如果工作目录中有一个名为-recurse:oops.cs的文件,则您的命令可能会使您感到惊讶。

The difference arises in the shells' default behavior when no file matches the given pattern. 当没有文件与给定模式匹配时,shell的默认行为会有所不同。 By default, bash falls back to guessing that you meant the * to be a literal, which is in fact what you meant. 默认情况下, bash会猜测您将*表示为文字,这实际上是您的意思。 zsh , on the other hand, exhibits the more traditional behavior of failing on account of the failure to match the pattern. 另一方面, zsh表现出更传统的失败行为,即由于无法匹配模式而导致失败。 bash can be induced to exhibit that behavior, too, by turning on its failglob option. 通过打开failglob选项, bash也可以表现出这种行为。

The best solution is to resolve the ambiguity by quoting the argument, or at least escaping the * in it. 最好的解决方案是通过引用参数或至少转义其中的*来解决歧义。 Both bash and zsh should handle this version fine without any special options: bashzsh都应该可以很好地处理此版本,而无需任何特殊选项:

mcs -recurse:\*.cs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM