windowsでunixコマンドを使う準備

# 前置き
windows におけるコマンド作業環境は、unix のシェルと比較して貧弱と言われています。普段 windows と unix の両方を使用している人は、コマンドプロンプトの使い勝手に不満を抱きやすいようです。

特に unix 系エンジニアは、unix のコマンド群に好意的な人が多く、反対に windows のコマンドプロンプトに批判的です。それにも関わらず、そのような人たちに与えられる端末は多くの場合 windows です。さらに悪いことに、それらの端末は個人的なカスタマイズが禁止されている場合が多く、彼らは貧弱な作業環境に甘んじています。

そこでこの記事では、windows 標準機能だけでそれらの不満を軽減する方法(windowsでunixらしいコマンドを使えるようにする方法)を提示します。

ただし、以下に提示する方法は windows の古典的な機能を活用する例であり、可能であれば Powershell([wikipedia](https://ja.wikipedia.org/wiki/Windows_PowerShell)) を使うことを検討する方が良いでしょう[^0]。

# コマンドのエイリアスを作成する

unix では、`pwd` でカレントディレクトリを表示することができます。コマンド作業においてカレントディレクトリの確認が必要になる場面は多く、`pwd` の使用頻度は高いと言えます[^1]。しかしながら、windows では、カレントディレクトリの確認を別のコマンドで行います。同様に unix における `ls` や `grep` といった使用頻度の高いコマンドも、windows では別のコマンドを使用します。

同様の機能はあるものの、別のコマンド名が割り当てられている（ので使い勝手が悪い）という問題は、コマンドにエイリアスを設定することで解決できます[^2]。

例えば、windows でカレントディレクトリを表示するためには、引数なしで `cd` を実行します。そこで以下のようなファイルを作成し、このファイルを PATH が通ったフォルダ[^3]に配置します。

```bat:pwd.bat
@cd
```

これでコマンドプロンプトで、`pwd` コマンドが使えるようになりました。

```bat:コマンドプロンプト
C:\user\hoge> pwd
C:\user\hoge
```

同様に、`ls` は `dir /b`、 `grep` は `findstr` で再現できます。ただし、これらのコマンドは引数を受け取るために `%*` を追加する必要があります。

```bat:ls.bat
@dir /b %*
```

```bat:grep.bat
@findstr %*
```

```bat:コマンドプロンプト
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 の先頭を表示するコマンドは以下のようになります。

```bat:コマンドプロンプト
C:\user\hoge> cscript //nologo C:\temp\bat\head.vbs example.txt
...
```

たった一つのコマンドを実行するためには冗長すぎて、これでは使い勝手以前の問題です。

この問題は、wsh スクリプトをバッチファイルから間接的に呼び出すことで解決できます。以下のようなフォルダ構成のときのバッチファイルを示します。

```bat:コマンドプロンプト
C:\user\hoge> tree /f C:\temp
C:\temp
├─bat
│      head.bat
└─scripts
       head.vbs
```
```bat:head.bat
@cscript //nologo %~dp0\..\scripts\head.vbs %*
```

このような構成にしておくことで、PATH を通すフォルダは C:\temp\bat だけで済み、bat と vbs を分けて管理することができるようになります。

# コマンドとして VBScript を作成する場合のテンプレート

参考として VBScript でコマンドを再現する場合に使用しているテンプレートを以下に例示します。

```vbnet:template.vbs
' [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


' 以下にコマンド本体の処理を記述する

```

---
[^0]: Powershell ではスクリプトの実行が無効にされています。有効にするためには管理者権限が必要です。
[^1]: windows ではプロンプトがカレントディレクトリになっているので、それほど使用頻度は高くないかもしれませんが……。
[^2]: doskey コマンドを使用することもできますが、この記事では触れません。
[^3]: PATH が通ったフォルダについては[参考記事](http://qiita.com/asterisk9101/items/7f1924a1402a4c9825e7)があります。