java - Windows JVM 命令行参数上的尾随星号在 cygwin bash shell 中被通配

标签 java scala cygwin command-line-arguments glob

更新:在 cygwin bash shell 中运行基于 JVM 的命令行工具时会出现此问题。虽然我最初认为这与 Scala 有关,但它是 Windows JVM 特有的。这可能是 MSDN 库中重大更改的结果,请参阅下面的评论。

我正在编写一个 scala 实用程序脚本,它采用文字 java 类路径条目并对其进行分析。我希望我的主要方法能够接收带有尾随星号的命令行参数,例如“/*”,但在 cygwin bash session 中运行时似乎无法做到这一点。

这是我的 scala 测试脚本,它显示命令行参数:

# saved to a file called "dumpargs.sc"
args.foreach { printf("[%s]\n",_) }

我希望能够用星号作为参数来调用它,如下所示:

scala -howtorun:script dumpargs.sc "*"

当我在 CMD.EXE shell 中运行它时,它会执行我期望的操作:

c:\cygwin> scala.bat -howtorun:script dumpargs.sc "*"
arg[*]
c:\cygwin>

同样,当在 Linux bash shell 中测试时,唯一的命令行参数由一个星号组成,这也是预期的。

用 C 编写的类似命令行参数转储程序会打印一个裸星号,无论它是从哪个 shell(CMD.EXE 或 bash)运行的。

但是当在 cygwin bash shell 中运行相同的测试时,星号将被通配,列出当前目录中的所有文件。通配符发生在 bash 下游的某个地方,否则 C 转储程序也会失败。

问题很微妙,它发生在 JVM 收到星号参数之后、JVM 调用 main 方法之前的某个地方。但 JVM 仅根据正在运行的 shell 环境中的某些内容来匹配星号。

在某些方面,这种行为是一件好事,因为它通过隐藏运行时环境、Windows 与 Linux/OSX 等之间的差异来支持脚本可移植性(类 UNIX shell 倾向于 glob,而 CMD.EXE 则不然)。

迄今为止解决该问题的所有努力都失败了:

即使我允许依赖于操作系统的技巧,我也尝试了以下所有操作(来自 bash session ):

"*" '*' '\*' '\\*'

以下内容几乎可以工作,但是半引号作为参数值的一部分到达,然后必须被我的程序删除:

"'*'"

同样的问题,但不同类型的不需要的引号通过:

'"*"' or \"*\"

需要的是一个系统属性,或者一些其他机制来禁用通配符。

顺便说一句,这个问题的一个变种是无法利用通过指定“-classpath 'lib/*'”将 jar 文件目录添加到类路径中的好方法(自 java 1.6 起)。

需要有一个系统属性,我可以设置它来在提供自己的通配符的 shell 环境中运行时禁用此行为。

最佳答案

此问题是由 JVM 中的一个已知错误引起的,记录如下:

https://bugs.openjdk.java.net/browse/JDK-8131329

同时,为了解决这个问题,我通过环境变量传递参数。

这是我的“myScalaScript”中发生的事情:

#!/usr/bin/env scala
for( arg <- args.toList ::: cpArgs ){
  printf("[%s]\n",arg)
}

lazy val cpArgs = System.getenv("CP_ARGS") match {
  case null => Nil
  case text => text.split("[;|]+").toList
}

以下是从 bash 调用脚本的方式: CP_ARGS=".|./lib/*"myScalaScript [可能是其他无问题参数]

这是它在所有测试环境中打印的内容:

[.]
[./lib/*]

这里有一个更好的修复方法,它隐藏了脚本中的所有肮脏内容,并且在主循环中更加传统。

新脚本:

#!/bin/bash
export CP_ARGS="$@"
exec $(which scala) "$0"
!#
// vim: ft=scala

for( arg <- cpArgs ){
  printf("[%s]\n",arg)
}

lazy val cpArgs = System.getenv("CP_ARGS") match {
  case null => Nil
  case text => text.split("[;|]+").toList
}

关于java - Windows JVM 命令行参数上的尾随星号在 cygwin bash shell 中被通配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37037375/

相关文章:

java - 我如何从 aws cloudwatch 的特定指标中获取数据?

scala - haxe 中的高级模式匹配(与 scala 示例相比)

scala - 抽象成员类型的值

c - 在 VS 2013 和 Cygwin 中使用 fork()

java - 在java中设置静态对象

java - Shell 排序算法比归并排序算法有何优势?

scala - 奇怪的 Scala 元组行为

shell - 在 Linux (CygWin) shell 脚本中锁定文件(并检测该锁定)

segmentation-fault - EXPECT_CALL 上的 gmock 段错误

Java泛型,返回什么而不是-1