前置き
windows におけるコマンド作業環境は、unix のシェルと比較して貧弱と言われています。普段 windows と unix の両方を使用している人は、コマンドプロンプトの使い勝手に不満を抱きやすいようです。
特に unix 系エンジニアは、unix のコマンド群に好意的な人が多く、反対に windows のコマンドプロンプトに批判的です。それにも関わらず、そのような人たちに与えられる端末は多くの場合 windows です。さらに悪いことに、それらの端末は個人的なカスタマイズが禁止されている場合が多く、彼らは貧弱な作業環境に甘んじています。
そこでこの記事では、windows 標準機能だけでそれらの不満を軽減する方法(windowsでunixらしいコマンドを使えるようにする方法)を提示します。
ただし、以下に提示する方法は windows の古典的な機能を活用する例であり、可能であれば Powershell(wikipedia) を使うことを検討する方が良いでしょう1。
コマンドのエイリアスを作成する
unix では、pwd
でカレントディレクトリを表示することができます。コマンド作業においてカレントディレクトリの確認が必要になる場面は多く、pwd
の使用頻度は高いと言えます2。しかしながら、windows では、カレントディレクトリの確認を別のコマンドで行います。同様に unix における ls
や grep
といった使用頻度の高いコマンドも、windows では別のコマンドを使用します。
同様の機能はあるものの、別のコマンド名が割り当てられている(ので使い勝手が悪い)という問題は、コマンドにエイリアスを設定することで解決できます3。
例えば、windows でカレントディレクトリを表示するためには、引数なしで cd
を実行します。そこで以下のようなファイルを作成し、このファイルを PATH が通ったフォルダ4に配置します。
@cd
これでコマンドプロンプトで、pwd
コマンドが使えるようになりました。
C:\user\hoge> pwd
C:\user\hoge
同様に、ls
は dir /b
、 grep
は findstr
で再現できます。ただし、これらのコマンドは引数を受け取るために %*
を追加する必要があります。
@dir /b %*
@findstr %*
C:\user\hoge> ls C:\temp\bat
pwd.bat
ls.bat
grep.bat
C:\user\hoge>
C:\user\hoge>
C:\user\hoge> ls C:\temp\bat | grep /I LS
ls.bat
同等のコマンドが windows に無い場合
unix と同等のコマンドが無い場合は wsh(windows script host) を持ち出す必要があります。wsh(vbscript, jscript) の使い勝手については賛否の分かれるところではありますが、大抵の unix コマンドを再現できます。
様々なコマンドの動きを再現できる wsh ではありますが、コマンドプロンプトから直接呼び出すと非常に冗長になってしまいます。例えば head
を再現する head.vbs を作成した場合、sample.txt の先頭を表示するコマンドは以下のようになります。
C:\user\hoge> cscript //nologo C:\temp\bat\head.vbs example.txt
...
たった一つのコマンドを実行するためには冗長すぎて、これでは使い勝手以前の問題です。
この問題は、wsh スクリプトをバッチファイルから間接的に呼び出すことで解決できます。以下のようなフォルダ構成のときのバッチファイルを示します。
C:\user\hoge> tree /f C:\temp
C:\temp
├─bat
│ head.bat
└─scripts
head.vbs
@cscript //nologo %~dp0\..\scripts\head.vbs %*
このような構成にしておくことで、PATH を通すフォルダは C:\temp\bat だけで済み、bat と vbs を分けて管理することができるようになります。
コマンドとして VBScript を作成する場合のテンプレート
参考として VBScript でコマンドを再現する場合に使用しているテンプレートを以下に例示します。
' [usage]
' 名前
' コマンド名
' 説明
' 詳細な説明
' オプション
' /version
' コマンドのバージョンを表示して正常終了する。
' /?, /help
' ヘルプを表示して正常終了する。
' 注意事項・ライセンス
' [version]
' command version 1.0
option explicit
' 関数定義
function view(byval label)
' usage などを表示する
dim fso, satream, line
set fso = CreateObject("Scripting.FileSystemObject")
set stream = fso.OpenTextFile(WScript.ScriptFullName)
do while not stream.AtEndOfStream
line = stream.ReadLine()
if line = "' [" & label & "]" then
do while not stream.AtEndOfStream
line = stream.ReadLine()
if left(line, 1) <> "'" then exit do
call WScript.Stdout.WriteLine(mid(line, 3))
loop
end if
loop
end function
' グローバル変数(主にコマンドラインオプションで変更される値と引数のリスト)
dim parameters..., arguments
...
set arguments = CreateObject("System.Collections.ArrayList")
' オプションと引数の解析
dim arg
for each arg in WScript.Arguments.Count
select case arg
case "/?", "/help"
call view("usage")
call WScript.Quit(0)
case "/version"
call view("version")
call WScript.Quit(0)
case else
call arguments.Add(arg)
end select
next
' 以下にコマンド本体の処理を記述する