GroovyはWindowsで!(感嘆符)が入ったディレクトリで起動できない

どうも、ラルフです

内容は表題の通り、動かないよってだけなので、少なくともこの記事では動作させるところまではできていません。

内部でどのような処理が行われているせいで起動できない っていうものの忘備録的な感じです。


Groovy は便利なもので、JREさえ入っていれば勝手に検索して起動してくれ、更にユーティリティクラスも結構あるという色々といい感じのものが入っています。

さらに、ポータブルに環境を持ち出すことも可能なので、動作させるものもJarにするより手軽に起動できます。

しかしながら、WindowsでGroovyが入っているフォルダ(親フォルダ含む)に ! (感嘆符) が入っていると起動できなくなるというのを報告で受けたので、それを調査してみました。

環境は、Windows 10 と Groovy 2.5.0-beta1 です。

Cドライブ直下に hoge! と言った感じのディレクトリを作り、その中にGroovyのバイナリと Groovyスクリプト、起動用batファイルを配備します。

こんな感じの構造で用意しています。

ここで、 run.bat を起動すると、

というエラーで起動できません。

なお、ディレクトリ名から ! を取り除くと、正常に Hello World と出力されます。

原因を探っていきましょう。

Groovyを起動している際、環境変数 DEBUG に何らかの文字が入っていると起動スクリプト内の @echo off が実行されなくなるので、バッチファイルを編集します。

この状態で起動すると、Groovy の起動用バッチファイル内部での実行されているコマンドが出力されます。

出力結果からカレントディレクトリの表示などを消したバージョンが以下です。

ここで注目するのは、156行目の、実際に java.exe を起動させている部分で、hoge! ディレクトリが全部 ! が外れて hoge ディレクトリとして呼び出してしまっています。

この原因は、Windowsのバッチファイルで使用できる遅延環境変数を Groovy の起動スクリプト内で使用しているからです。

http://qiita.com/yasumodev/items/c0387913b79d56d6fd52

http://qiita.com/sawa_tsuka/items/c7c477cacf8c97792e17

Groovy を起動させるスクリプトの本体である、 bin/startGroovy.bat を見ると、以下のような記述があります。

この enabledelayedexpansion がで遅延環境変数が定義されると、感嘆符に対してエスケープが必要になります。( !VAR! が遅延環境変数になるので)

https://superuser.com/questions/902619/how-do-i-make-exclamation-marks-show-using-echo

基本的には、感嘆符の前に ^^ をつけてエスケープすればいいのですが、今回は、Groovy内部で不定の回数展開される変数 GROOVY_OPTS などで使用されているため、単純に  GROOVY_HOME を指定したり、呼び出し時のスクリプトパスを工夫するのでは起動しません。

仕方がないので、 startGroovy.bat に手を少し加えてみます。

感嘆符で検索すると、このバッチファイル内部で遅延環境変数が使われているのは、 JAVA_HOME が未定義時に PATH から有効な Java ランタイムを検索する部分で使われています。

奇しくも Groovy 便利機能の一つが今回の引き金になってしまいました。

とりあえず、遅延環境変数はこの範囲内だけで動いていれば問題ないはずなので、この範囲内だけ有効になるようにしてみます。

ファイル先頭の enabledelayedexpansion を消した上で、上記範囲を以下のように書き換えます。

この状態で run.bat を起動してみましょう。すると、別のエラーに変わっているはずです。

java.io.FileNotFoundException: C:\hoge、groovy.lang.GroovyRuntimeException: Unable to load module META-INF descriptor ということで、META-INF を探しに行っているようですが、どうも検索しているファイルがおかしいです。

予想するに感嘆符が区切りとして認識されてしまっているので、Groovyのライブラリロードで死んでいるのかなーと言う感じです。

とりあえず、この内部の探索と修正は非効率的で、感嘆符がつかないようにさえすればそもそも回避できるので、ここで調査は終了とします。

Contents

結論

フォルダ名は英数半角及び特殊じゃなさそうな記号で構成しよう

Technology

Posted by Ralph