PowerShellで変数を引数にしてコマンドを実行するときの注意

  Windows

今までコマンドプロンプトばかり使っていた私が、PowerShellを使い始めて戸惑った点の備忘録です。

分かりやすくするためにJavaで下記のようなプログラムを書きました。

public class Main {
    public static void main(String[] args) {
        System.out.print("key1=");
        System.out.println(System.getProperty("key1"));
        System.out.print("key2=");
        System.out.println(System.getProperty("key2"));
    } 
}

このプログラムに対して、java -Dkey1=abc -Dkey2=def Main.java とすると実行結果は以下になります。

E:\>java -Dkey1=abc -Dkey2=def Main.java
key1=abc
key2=def

-Dkey1=abc -Dkey2=defという部分を環境変数に設定して実行することもできます。

E:\>set OPTIONS=-Dkey1=abc -Dkey2=def

E:\>java %OPTIONS% Main.java
key1=abc
key2=def

さて、同じことをPowerShellで行ってみます。

PS E:\> java -Dkey1=abc -Dkey2=def Main.java
key1=abc
key2=def

ここまではコマンドプロンプトと同じです。引き継いだ環境変数をそのまま使って実行してみます。

PS E:\> $env:OPTIONS
-Dkey1=abc -Dkey2=def
PS E:\> java $env:OPTIONS Main.java
key1=abc -Dkey2=def
key2=null

なんとkey1"abc -Dkey2=def"が設定されてしまいました。これは環境変数だけでなく、PowerShellの変数でも同じで、1変数が1引数として渡ってしまうようです。

PS E:\> $OPT="-Dkey1=ABC -Dkey2=DEF"
PS E:\> $OPT
-Dkey1=ABC -Dkey2=DEF
PS E:\> java $OPT Main.java
key1=ABC -Dkey2=DEF
key2=null

Javaを起動するバッチなどで実行時オプションをひとまとめにして 環境変数JAVA_OPTIONSに設定しておくことをよくやっていましたが、これができなさそうです。

結論としましては、splitメソッドを使って空白で分割することで問題を回避できるようです。バッチをシェルスクリプトへ移植する際は気を付けないといけませんね。

PS E:\> $OPTS = ($OPT.split(' '))
PS E:\> java $OPTS Main.java
key1=ABC
key2=DEF
PS E:\>

ちなみに$OPTSは配列型になっているみたいです。

PS E:\> $OPTS.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String[]                                 System.Array

PS E:\>

追記。久しぶりにコマンドラインからJavaのプログラムを実行してみたらコンパイルしないでも実行できるようになっててビックリ。

LEAVE A COMMENT