(Tips)(Windows7 HomePremium 64bit版)(Windowsでスクリプトを実行する時にshebang的な解釈をさせてみる)

Tips一覧はこちら http://d.hatena.ne.jp/morakana/20110704/1310703995
ちょこっと改良版は→ http://d.hatena.ne.jp/morakana/20131031/1383206446


 WindowsRubyPerl などのスクリプトを実行する場合
基本的にはコマンドプロンプトから
ruby aaaa.rb
perl bbbb.pl
のようにして実行しますが
これはパスの通った所のバージョンのインタプリタで実行しているという事になりますね

 ここでもし、バージョン依存したスクリプトが何個もある場合
そのつどバージョンに合ったPATHに環境を変更させたりするのはなかなか面倒ですよね?
各バージョンのirbやgemを操作する必要がない(スクリプトを実行するだけでいい)場合は
PATHの変更を一時的にでもするのはなかなか億劫に感じるものがありますよね

 そこで
Linux系のように実行するインタプリタの場所を一行目で指定できれば楽になるかもしれない?
とふいに思い立ったので、お試しに考えてみました
今回は・・・なんとbatファイルを組んでみる事に! 笑)
何故batファイルなのかというと
「1. batファイルにファイルを関連付けする事が出来る」
「2. batファイルで処理するから新しいコマンドプロンプトを開かないように動作させる事が出来る」
「3. batファイルだしあまりWindowsのバージョンに依存しないだろう」

という感じですかね

 基本的な考え方は
スクリプトの一行目を解釈して「#!」で始まっているなら
それをshebangとみなして実行するbatファイル「shebang.bat」を作り
スクリプトファイルはshebang.batに拡張子で関連付けをする
スクリプトを実行する場合はスクリプト名を入力してEnterキー
という簡単なものです、でそのbatファイルは・・・
batファイル名:shebang.batエンコード:Shift-JIS、 フォーマット:DOS形式(CRLF)

@echo off IF NOT EXIST %1 ( echo File not found. GOTO END_OF_BAT ) set /P FL=<%1 IF NOT "%FL:~0,2%"=="#!" ( echo not found shebang. GOTO END_OF_BAT ) echo ^<%FL:~2%^> echo. %FL:~2% %* :END_OF_BAT
ちなみに shebangとは「シバン」とか「シェバン」と読むらしいです 笑)

 あとは .rb とか .pl を shebang.batに関連付けるだけですね
スクリプトの一行目は
rubyなら
#!D:/ruby/bin/ruby -Ku
perlなら
#!C:/Perl64/bin/perl
などといった感じですかね、つまりここのパスを変えればLinuxのようにインタプリタを変更する事が出来ます
パス指定は「/」で区切ってますが「(半角の)¥」でもOKです
(というか、古いWindowsだと「(半角の)¥」じゃないと駄目かも?)
検証はしてませんが、RubyPerl以外でもshebangのような動きをするスクリプトなら通用するとは思います

 気づかないとハマりそうな問題点は
スクリプトのファイルエンコーディングは「Shift-JIS」でも「UTF-8」でも問題はありませんでしたが
ファイルフォーマットは「dos形式(いわゆるCRLF)」じゃないとうまく動かないようです
おそらく、改行がCRLFじゃないとbat処理側がきちんと改行として認識しないのが原因なんじゃないか?と推測してます
なのでインタプリタ側が対応してても、スクリプトUNIX形式(LF)とかMac形式(CR)では書き出さないでください

 まあ、思い立ってとりあえず作っただけですので殆ど検証は出来ていません
色々と共存のさせ方とか関連付けの兼ね合いなどで、どういう副作用を起こすか分かりませんので
もし問題が起こっても自力でなんとか修復できる人だけお試しください 笑)





 追記:コマンドライン引数が反映しないトラブル
shebang.bat testscript.rb test1 test2
とやるとコマンドライン引数をちゃんと受け取っているのに
.rbファイルを右クリックメニューなどからshebang.batに関連付けした後に
testscript.rb test1 test2
とやるとコマンドライン引数をきちんと受け取っていない問題に遭遇した人も居るかもしれません
私もこうなったのであわてて調べてみました 笑)
この問題は関連付けが理想的に行われていないのが原因の可能性が高いです
関連付けを正しく再構築してみるとうまく行くようになるかもしれません

 私の場合だとRubyでこの症状になって、そこから回復したので、今回はRubyのケースとして書きます
他の言語の場合も読み替えながらやってみるとうまく行く事があるかもしれません

 まずは .rbファイルに対する現在の関連付け関連情報を一旦徹底的に削除します
レジストリをいじるので慎重に作業を進めるようにします
まず三ヶ所です
[HKEY_CURRENT_USER\Software\Classes\.(拡張子)]
[HKEY_CURRENT_USER\Software\Classes\(拡張子)_auto_file]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.(拡張子)]
を探して削除してください
つまり
[HKEY_CURRENT_USER\Software\Classes\.rb]
[HKEY_CURRENT_USER\Software\Classes\rb_auto_file]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.rb]
を削除するということになります
レジストリエディタをいじるのが めんどい or 怖い 場合は
regファイルを作って消す方法もあります
regファイル名:unreg_assoc_rb.regエンコード:Shift-JIS、 フォーマット:DOS形式(CRLF)

REGEDIT4 [-HKEY_CURRENT_USER\Software\Classes\.rb] [-HKEY_CURRENT_USER\Software\Classes\rb_auto_file] [-HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.rb]
「REGEDIT4」は必ず一行目に書いてください、一行目が空行とかだと怒られます 笑)

 続いて二ヶ所をチェック
OS が Win7 64bit などの場合は 管理者権限でコマンドプロンプトを起動し
assoc .rb
とします、.rbに対してタイプが設定されていないと
「拡張子 .rb のファイルの関連付けが見つかりません」
という答えが返ってきます
もしも設定されていると「.rb=RubyScript」とか「.rb=ruby」みたいな答えが返ってきますので、さらに
ftype RubyScript
などと、返って来た名前を指定してftypeを実行します(「.rb=ruby」だったら「ftype ruby」)
すると「RubyScript="C:\ruby\bin\ruby.exe" "%1"」みたいな感じの答えが返ってくるかもしれません
返って来ない場合もあります
(答えが無い場合→「ファイル タイプ 'RubyScript' が見つからないか、オープン コマンドが関連付けられていません。」)
以上の二つに関して、もしも値が設定されていたらそれらの値を削除します
いずれも「=」だけを書くと削除できます

assoc .rb=
ftype RubyScript=
 これで .rbファイルに関する関連付け情報は無くなりました

 続いて関連付けを復活させる番です
まず .rbファイルの ftypeを定義します
assoc .rb=RubyScript
でいいでしょう
そして一番重要な所の定義です
ftype RubyScript="(shebang.batへのフルパス)" "%1" %*
とします
私の場合だと「RubyScript="D:\DLL\shebang.bat" "%1" %*」みたいな感じになってます
タイプミスshebang.batへのパスが間違ってなければ
この時点でコマンドプロンプトから、rubyスクリプトファイル名を書いてEnterキーだけで
関連付けが働いて起動できるようになってるはずです
コマンドライン引数も受け付けるようになってると思いますし
結果をパイプしたりリダイレクトする事なども問題なく出来るようになってるはずです

 以上で .rbに対する関連付けの再設定でした! 笑)
文章にすると異様に長くなるけど、実際にやってみるとそうでもありませんよ? 冷汗・・・)