さて、Cygwin や WSL から *.js や *.vbs を cscript.exe に食わせる方法なのだが、
ふと Cygwin や WSL では少なくとも bash の場合、実行ビットが立ってて shebang がないと、shell script 扱いして bash に食わしてる事に気付いた。
んで、BAT ファイルに WSH を埋め込む方法は基本的にバッチファイルの頭の部分を WSH のコメントに見せかけつつ、cmd.exe のコマンドとしては有効な命令とすることで、その中から cscript を呼び出すテクニックなんだけど、んじゃぁ 1 行目を WSH にコメント扱いさせて、bash 的に実行可能な構文にしてやれば、shebang 代わりになるじゃないかという事に気付いてしまったわけである。
つまり、JScript の場合は、// から始まるコマンドの絶対パス、VBScript の場合は '...' で囲ったコマンド名または '' からコマンドを始めればよいということになる。
ただし、Cygwin の場合、// で始めると
UNC 扱いされてしまうため問題がある。
試してみたところ、これは、/// とすると普通にフルパスとして扱えるという事が確認出来た。
という事で、上記の思い付きを実装してみたところ、以下のようにすることで目出度く目的を達することが出来た。
hello.js.sh
///usr/bin/env cscript.exe //NoLogo "$0" "$@"; exit $?
WScript.Echo("hello");
hello.vbs.sh
''/usr/bin/env cscript.exe //NoLogo "$0" "$@"; exit $?
WScript.Echo "hello"
ただし、このままだと、"$0" のパスが cscript.exe に解釈不能な場合があるので、cygpath, wslpath を用いて UNIX 環境 → win32 環境の path 変換をする wrapper を作り /usr/bin/env の代わりに使う方が良いと思われる。
因みに、これを思い付いたのは、
WSH Wrapper なる bash script をほぼ書き終えた直後で、書いてたものがなんか無駄になってしまった感があるんだけど、割と応用は効きそうだし、上記のパス変換の問題もあるので、後日暇を見て調整してから公開したい。
以上、結果的に bash script をベースに WSH を埋め込んだのハイブリッドスクリプトが書けるねという話になった。
なお、上記ではファイル名を *.sh としているが、バッチファイルと違って、実行ビットさえ立ってればファイル名は自由なので、*.sh はおろか *.js や *.vbs すら付与する必要はないので念のため。
追記:
cygpath, wslpath への簡易対応してみた。
hello.js.sh
///bin/true;w=( $(type -p cygpath wslpath) );cscript.exe //NoLogo "$("$w" -w "$0")" "$@";exit $?
WScript.Echo("hello");
hello.vbs.sh
'':;w=( $(type -p cygpath wslpath) );cscript.exe //NoLogo "$("$w" -w "$0")" "$@";exit $?
WScript.Echo "hello"
あと、改行コードは CR LF (0x0d 0x0a) だと動かないので LF (0x0a) にする事。