有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

考虑以下简单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。类(目录中的文件)

可以关闭此行为:

$ set -f
$ echo *
*

现在*还没有被扩展

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

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

引用或逃避也无济于事:

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

谁是罪魁祸首,Shell还是Java?看起来是JVM,因为python程序运行良好:

Python文件a.py

import sys
print  sys.argv[1:]

使用通配符运行python程序:

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

没有扩张

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


共 (1) 个答案

  1. # 1 楼答案

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

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

    这意味着,当您从Unix shell运行Windows程序时,可能会有两次全局扩展的风险

    以下是负责这件事的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子系统,它比CygWin更精确地模拟UNIX环境。p>