WSL2環境でWindowsのコマンドを使ってみた

# はじめに
WSL2環境では、linux端末からWindows側のコマンドを使うことができる。WSL2環境は随分前から利用していたのだが、ついこの間までこの事実を知らなかった。
今ではすっかり活用しているので、使い方についてのメモを備忘録として記すことにする。

# WSL2環境について
Windows10/11上で軽量仮想マシンを起動し、この上でLinuxを動かして利用するものである。導入方法はネット上で簡単に調べられるのでここでは割愛するが、私はMicrosoft StoreからUbuntu-20.04LTSを入手して使っている。Windows11になってからは、Windows上でXサーバアプリを起動することなく、Ubuntuの各種ターミナルアプリやGUIアプリを動かすことが可能になっており、WindowsアプリとLinuxアプリを同一デスクトップ上でシームレスに使えるようになっている。以前の仮想マシン+Linuxのシステムは、シームレス利用というよりはPCを2台持つ代わりに使うもの、という感じだったが、WSL2環境はWindowsとLinuxを自分の好みで混ぜて使う感じで、開発作業に両方の環境が必要な自分のような人間にとってはかなり便利なものである。

Windowsターミナルを立ち上げ、ターミナル上でbashと打ち込むと、WSL2環境が立ち上がってbashのコマンドプロンプトが返ってくる。それ以降はLinux環境に移行してLinuxのコマンドが使える。この状態からGUIアプリをコマンドを叩いて立ち上げることが可能である。また、Windows側のボリュームはLinux側のディレクトリにマウントされているため、bash環境でWindows側のデータにアクセスすることができる。WSL2環境の立ち上がりは、私の試した環境(3年位前のノートPC用Core i7)で数秒程度であり、以前の仮想マシン起動してLinux起動、というものとは使い勝手が明らかに違うものになっている。
『Microsoftが本気でLinuxに取り組むとこうなるのか』と、かつてLinuxを仇扱いしていたMicrosoftを知っている私にとってはかなりの驚きである。その真骨頂とも言えるのが、Linux環境からWindowsコマンドをあたかもLinuxコマンドを扱うかのように使える機能である。

# 本題:WSL2環境でLinux環境からWindowsコマンドを使う
## 手順
###  WSL2環境の起動方法
* Windowsターミナルを起動
* ターミナルでbashと入力すれば、WSL2上のUbuntuが起動(bashのプロンプトが返ってくる)

### 例1:メモ帳起動
```
bash$ notepad.exe
```
これでWindowsのメモ帳が普通に起動する。WSL2のUbuntu環境ではWindowsコマンドにpathが通っているので、tabキーでコマンド名が補完される。これはこれで最初は驚きだった。

### 例2:メモ帳でUbuntu側にあるテキストファイルを読み込ませる場合
```
bash$ notepad.exe $(wslpath -w ./sample.txt)
```
WindowsアプリからはUbuntu側のファイルが見えない場合があり、これを解決するのがwslpathコマンドである。これはWSL2環境オリジナルのもので、
```
bash$ wslpath -w ./sample.txt
```
と入力すると、Windowsから見える形式でファイル名を標準出力に返してくれる。これの便利なところは、ファイル名変換をローカルボリュームだけでなく、ネットワークドライブについても対応してくれるところである。例えば、Ubuntu側でNASのボリュームをCIFSマウントして使っている場合でも、wslpathコマンドでファイル名を変換すれば、このボリューム上のデータであってもWindowsアプリに読み込ませることができる。

元々、Windows側はUbuntuのボリュームをまるごと全部マウントしているので、そこからたどればUbuntu上のボリュームはすべて見ることができるため、それはできて当然だろうなと勝手に理解している。wslpathによる指定は、ファイル書き込み時ももちろん有効。

※WindowsアプリからUbuntu側のファイルがwslpathコマンドなしで見える場合：
* コマンドを起動するカレントディレクトリにあるファイル
* コマンドを起動するカレントディレクトリからの相対パスで記述されたファイル

### 例3:Windows環境のffmpegを使う
Ubuntu環境にももちろんffmpegはあり、普通に使うことは可能だが、あくまでも仮想環境で動かしているため、PCのハードウェアが持つcodec等のハードウェア支援機能を簡単に使うことができない。レンダリング時にこれを使えるか使えないかでスループットに数倍以上の違いが出てくる。このような場合に、Windows環境のffmpegを使えば、Ubuntu環境下でもハードウェア支援機能を利用できるため、Ubuntu側のffmpegを遅いのを我慢して使う必要はなくなる。

最近、cudaをWSL2環境から使えるようになったとのこと。これはこれですごいなと思うが、もちろんそのための設定は必要とのことで、ポン付けで使えるようなものではない。現状はそういう特別な対応が必要という認識をもっている。

一方、ffmpegはその機能を色々使いこなそうと思うと、コマンドオプションにソースコードを書くような作業をしなければならず、そうなるとワンライナーでコマンドを書き連ねるのではなく、スクリプトを書いて動かすことが多くなる(エラー回避のため、少なくとも自分はそうする)。こうなると、スクリプト記述をすべてUbuntu上で行っている自分としては、ほとんど触ったことのないWindowsバッチファイルでの記述ではなく、bashで書きたい、というかbashでなければ書けない。しかし、このわがままをWSL2は可能にしてくれる。具体的には、Ubuntu上のffmpegを使う前提で書かれたbashスクリプトを一部修正することでそのまま使うことができる。例えば、H264形式で動画をエンコードする例:

```
(ubuntu記述(修正前)) -> (Windows記述(修正後))
ffmpeg  -> ffmpeg.exe
$infile -> $(wslpath -w $infile)
-vcodec libx264 -> -vcodec h264_* (*:nvenc(NVIDIA), qsv(INTEL), etc)
$outfile -> $(wslpath -w $outfile)
```
vcodecのところは、環境に合わせて書き換えが必要。

なお、python.exeも同じ様にubuntu側から使えるが、WSL2上のpythonとの差異がffmpegほど大きいとは思えないため、個人的には使っていない。もしかしたら、グラフィック関係はpython.exeを使った方が高速なのかも知れない。

# 最後に
WindowsとUbuntuがシームレスに使えるようになって個人的にはかなり便利だと感じているが、bashのスクリプトの中までも混ぜてしまうと、WSL2以外の環境へのポータビリティはなくなってしまうので、ここは考えどころかと思う。どちらの環境でも使えるようにスクリプトを書けばよいとは思うが、手間が増えるので今後の課題ということにしている。