msys上だとRubyのワイルドカード展開がやっかい

あるRubyスクリプトで、オプションとしてワイルドカードを利用した指定をできるようにしようとしてみたのですが、僕の期待に反してうまく動いてくれませんでした。
UNIX等のシェル上において通常、ワイルドカード指定をした場合はシェルによって展開されます。しかし、Windows上ではシェルが展開をしないため、Windows上でRubyを動かすときはRubyワイルドカードの展開を行います。
ワイルドカード展開をさせたくない時は、シングルクォテーションで括ってやればOKです。…OKな、はずでした。
ところがどっこい、これがうまく動いてくれないんです。シングルクォテーションで括っても、ワイルドカード展開されてしまいました。試行錯誤したところ、シングルクォテーションで括ってからさらにそれをダブルクォテーションで括ると、ワイルドカード展開されないことがわかったのですが、さすがにこれは面倒です。
なんとかならないかと調べてみたところ、どうやらmsysがまずいらしいということがわかりました。具体的には、スクリプト呼び出し時に付けたクォートが、プロセス呼び出し時にははずされているのです。Rubyのソースファイル「win32.c」のNtInitializeあたりでGetCommandLine()で取得できるコマンドラインを出力するとよくわかります。
ruby -e 'p ARGV' '*.c' -c -h
このワンライナーを実行すると、msys上からか、コマンドプロンプト上からかで出力が異なります。

<msysの場合の出力>
c:\usr\local\bin\ruby.exe -e "p ARGV" *.c -c -h    # GetCommandLine()で取得できるコマンドラインの中身
["hoge.c", "hogehoge.c", "-c", "-h"]               # ワンライナーの実行結果

<コマンドプロンプトの場合の出力>
c:\usr\local\bin\ruby.exe -e 'p ARGV' '*.c' -c -h    # GetCommandLine()で取得できるコマンドラインの中身
["*.c", "-c", "-h"]                                  # ワンライナーの実行結果

msys上からだと、rubyのプロセスに渡される '*.c' のシングルクォートが外れているのがわかると思います。クォートが外れた状態でrubyに渡されるので、rubyは独自にワイルドカード展開を行ってしまうというわけです。

どう対処しようか。たっぷり悩んだ結果、次のように独自に加工してからオプションをrubyに渡すようにすることにしました。

#!/bin/sh
for elm in "$@"
do
  args[$i]="'${elm}'"
  i=$i+1
done
exec ruby -S -x $0 "{args[@]}"
#! ruby
p ARGV

msysが勝手にクォートを外すならば、もう一度こちらで付け直して、直接渡してしまえというもくろみです。実際はexec経由でrubyを立ち上げている以上、同様のことが起きて再びクォートを外すのではないかと思うのですが、うまくいってしまいました。う〜ん、いまいち納得がいきませんが、とりあえずこれで煮詰まっていたツールの機能を拡張できます。