如何在没有通配符扩展的情况下将*传递给java程序?

时间:2018-02-23 14:06:23

标签: java bash cygwin glob

考虑遵循简单的Java程序:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        System.out.println(Arrays.asList(args));
    }
}

Glob扩展通常由shell完成,而不是由JVM完成。例如,在Cygwin中:

$ echo *
Main.class

Cygwin将*扩展为Main.class(目录中的文件)

可以关闭此行为:

$ set -f
$ echo *
*

现在*尚未扩展。

但是,当将*传递给Java程序时,通配符会以某种方式扩展:

$ set -f
$ java Main *
[Main.class]

引用或转义也无济于事:

$ java Main '*'
[Main.class]
$ java Main \*
[Main.class]

谁是罪魁祸首,壳牌还是Java?它似乎是JVM,因为python程序运行正常:

Python文件a.py

import sys
print  sys.argv[1:]

使用通配符运行python程序:

$ set -f; python a.py *
['*']

没有扩张。

为什么JVM扩展通配符?这应该是Shell的功能,而不是JVM。如何关闭它?

1 个答案:

答案 0 :(得分:1)

在Unix上,glob扩展由shell处理,而不是由程序处理。

在Windows上,glob扩展由程序处理,而不是由shell处理。

这意味着当您从Unix shell运行Windows程序时,可能会有两次遍历glob扩展。

以下Windows OpenJDK source code对此负责:

/*
 * At this point we have the arguments to the application, and we need to
 * check with original stdargs in order to compare which of these truly
 * needs expansion. cmdtoargs will specify this if it finds a bare
 * (unquoted) argument containing a glob character(s) ie. * or ?
 */
jobjectArray
CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
{
   // (***snip***)
    NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,
                                                "expandArgs",
                                                "([Ljava/lang/String;)[Ljava/lang/String;"));

    // expand the arguments that require expansion, the java method will strip
    // out the indicator character.
    NULL_CHECK0(inArray = NewPlatformStringArray(env, nargv, argc));
    outArray = (*env)->CallStaticObjectMethod(env, cls, mid, inArray);

这里是它所调用的expandArgs

static String[] expandArgs(List<StdArg> argList) {
    ArrayList<String> out = new ArrayList<>();
      // (***snip***)
            try (DirectoryStream<Path> dstream =
                    Files.newDirectoryStream(parent.toPath(), glob)) {
                int entries = 0;
                for (Path p : dstream) {
                    out.add(p.normalize().toString());
                    entries++;
                }

我不知道是否可以禁用此行为。考虑在文件中传递数据,或使用Windows子系统Linux,它比CygWin更准确地模拟Unix环境。