2016-05-04 2 views
1

UPDATE:この問題は、cygwinのbashシェルでJVMベースのコマンドラインツールを実行しているときに発生します。もともと私はこれがScalaに関連していると思っていましたが、それはWindows JVM特有のものです。これは、MSDNライブラリの変更点を突破した結果かもしれません。以下のコメントを参照してください。Windowsでのアスタリスクの末尾JVMのコマンドライン引数はcygwinのbashシェルでglobbedされます

私は、リテラルJavaクラスパスエントリを取り、それを分析するscalaユーティリティスクリプトを作成しています。私の主な方法は、末尾のアスタリスク(例えば、 "/ *")をコマンドライン引数として受け取ることができますが、Cygwinのbashセッションで実行しているときは実行できません。

はここでコマンドライン引数を表示する私のScalaのテストスクリプト、です:

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

私はこのように、引数としてアスタリスクでそれを呼び出すことができるようにしたい:

scala -howtorun:script dumpargs.sc "*" 

これをCMD.EXEシェルで実行すると、期待通りの結果が得られます。

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

同様に、 Linuxのbashシェルでは、唯一のコマンドライン引数は、やはり期待どおり、裸のアスタリスクで構成されています。

Cで書かれた同等のコマンド行argsダンパープログラムは、実行されるシェル(CMD.EXEまたはbash)に関係なく、単一の裸のアスタリスクを出力します。

しかし、同じテストをcygwinのbashシェルで実行すると、アスタリスクはグロブになり、カレントディレクトリのすべてのファイルが一覧表示されます。グロブは、bashの下流のどこかで発生します。そうしないと、Cダンパープログラムも失敗するからです。

問題は微妙です。アスタリスク引数を受け取った後、JVMがmainメソッドを呼び出す前に、JVMのどこかで問題が発生します。しかし、JVMは実行中のシェル環境内の何かに基づいてアスタリスクをグロブするだけです。

ランタイム環境、Windows/Linux/OSXなどの違いを隠すことによって、スクリプトの移植性をサポートするため、この動作はいくつかの点で優れています(unixのようなシェルはglobになりがちですが、CMD.EXEしない)。

これまでの問題を回避するためにすべての努力が失敗した:

私はOS依存のトリックを可能にしていたとしても、私は(bashのセッションから)次のすべてを試してみた:

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

次はほとんど機能しますが、半分の重引用符は、引数の値の一部として到着した後、私のプログラムによって剥ぎ取られている必要があります

"'*'" 

同じ問題が、unwanの異なる種類

'"*"' or \"*\" 

グロブを無効にするためのシステムプロパティまたはその他のメカニズムが必要です。

ところで、この問題の1つのバリエーションは、 "-classpath 'lib/*'を指定することによって、jarファイルのディレクトリをクラスパスに追加することができない(Java 1.6以降) "

'globbing'を提供するシェル環境で実行しているときにこの動作を無効にするために設定できるシステムプロパティが必要です。

+0

問題が解消されている場合、Linuxのセッションでテスト。また、CMD.EXEセッションからscala.batを呼び出すと、アスタリスクを二重引用符で囲んで問題を回避できます。 scala.batを動作させることができるので、bash scalaスクリプトでこれを修正する機会があるかもしれません。 – philwalk

+0

https://msdn.microsoft.com/en-US/library/ms235497(v=VS.80).aspx – philwalk

+0

これはバグの原因かもしれません:https://bugs.openjdk.java.net/ JDK-7167744を参照してください。これはJava 1.7を指しますが、問題はまだ2016年5月現在の1.8にあります。 – philwalk

答えて

0

この問題はここでは説明し、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のから呼び出された方法は次のとおりです。 "| ./lib/*" CP_ARGS = myScalaScript [おそらく他の非problematic-ここで

[.] 
[./lib/*] 

スクリプト内のすべての意地の悪さを隠し、より良い修正、だし、次のとおりです。引数]

、ここではそれがすべてのテスト環境で印刷し何メインループではもう少し従来のものです。

新しいスクリプト:

#!/bin/bash 
export CP_ARGS="[email protected]" 
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 
} 
+0

これは修正ではなく回避策であるため、(うまくいけば)より良い回答が待っています。 – philwalk

+0

ところで、Windowsのbashシェルでは、 "ディレクトリ下のすべてのjar"クラスパスショートカット(例:-cp "./lib/*")の使用を妨げるので、jvmバグはかなり深刻であると考えます。 – philwalk

+0

Java 1.8.0_52(以前のバージョン)でWindowsで動作することが確認されたが、バックスラッシュが使用されている場合に限り、 "ディレクトリ下のすべてのjar"イディオムが検証されました。前方スラッシュは一般的にクラスパスを指定するためのWindows javaで動作しますが、この特定のイディオムでは機能しません。 – philwalk

関連する問題