Windows 10のLinux互換環境WSLからコマンドプロンプトのプログラムを呼び出す(バージョン1803対応版):Tech TIPS
さまざまなコマンドなどを組み合わせて自動処理したり、Windows系のツールが出力するメッセージを処理したりするなら、Linuxのツールの方が便利なことが多い。WSLからWindows系のコマンドを呼び出したり、組み合わせたりして使う方法を解説する。
対象OS:Windows 10バージョン1709以降(64bit版のみ)
WSLからWindowsのコマンドプロンプトのプログラムを呼び出して処理する
Windows 10に「WSL(Windows Subsystem for Linux)」をインストールすると、Linux向けのプログラム(バイナリファイル)をそのまま実行することができる。WSLのインストール方法については、TIPS「Windows 10でLinuxプログラムを利用可能にするWSL(Windows Subsystem for Linux)をインストールする」を参照していただきたい。
またTIPS「Windows 10のコマンドプロンプトからWSL上のLinuxコマンドを呼び出す」では、コマンドプロンプトからWSLのコマンドを呼び出して処理する方法を取り上げている。ここでは、先頭に「wsl 〜」と付けるだけで、WSL側のコマンドが起動できることを紹介した。
これとは逆に、WSL側からコマンドプロンプト側のプログラムやツールなどを呼び出すことも可能だ。本TIPSではその方法を紹介する。
WSLからコマンドプロンプトのプログラムを呼び出すには?
WSL側からWindows上のプログラムを直接呼び出す方法は簡単である。単に、起動したいプログラムのパス名を拡張子まで含めて指定すればよい。
例えばタスク一覧を表示するコマンド(実行ファイルは「C:\Windows\System32\tasklist.exe」)を実行したいのならば、「tasklist.exe」と指定する。コマンドプロンプト上で実行する場合は、拡張子の「.exe」を省略できるが、WSLから呼び出す場合は必ず拡張子まで指定する必要がある。
これ以外にも幾つか注意点があるのでまとめておく。
- コマンドプロンプト側のプログラムを起動するには、拡張子まで含めて指定する
- PATH環境変数に登録されていない場所にあるコマンドの場合は、フルパスで表記する
- コマンドプロンプト(cmd.exe)の内部コマンド(独立した実行プログラムファイルとして用意されていないコマンド)やスクリプトファイルなどを実行したい場合は、「cmd.exe /c dir」のように、先頭に「cmd.exe /c 〜」を付けて実行する
- バッチファイルの実行は、利用できるコマンドと文字コードに注意する
- コマンドプロンプト側のパス名を指定する場合は、特殊文字を「\」でエスケープするか、引用符で囲む
- Windows OS側コマンドはコードページ=65001(UTF-8)の環境で実行されるので、日本語文字列などが含まれる場合は注意する
以下、それぞれについて補足しておこう。
起動するコマンドは拡張子まで含めて指定
コマンドプロンプト側では、実行ファイルの拡張子は省略してもプログラムを起動できるが、WSL側から起動する場合は.exeや.batなどの拡張子も含めて全て指定する必要がある(ただしバッチでは実行できないコマンドが多くあるので注意。詳細は後述の「バッチファイルを実行したい場合は、利用できるコマンドに注意」参照)。CUIのツールだけでなく、GUIのプログラムでも起動できる。
PATH環境変数に登録されていないプログラムはフルパスで指定
コマンドプロンプト側で設定されているPATH環境変数の値は、WSL側にも引き継がれている。そのため、PATH環境変数で示される場所にあるコマンドならば、ファイル名と拡張子を指定するだけで起動できる。PATHの設定についてはTIPS「Windows 10でPath環境変数を設定/編集する」を参照していただきたい。
だがPATHが通っていない場所にあるコマンドを実行したい場合は、WSL上のフルパス名で指定する必要がある。
内部コマンドなどは「cmd.exe /c 〜」で実行
コマンドプロンプトの内部コマンドや、内部コマンドを含むバッチファイルなどはWSL側から直接実行することができない。それらを実行したい場合は、cmd.exeに/cオプションを付けて「cmd.exe /c 〜」のようにして、コマンドプロンプト側で実行させる。
バッチファイルを実行したい場合は、利用できるコマンドに注意
バッチファイルでは、例えば「@echo off」や「setlocal」「echo 〜」「if 〜」といった内部コマンドをよく使うが、これらが含まれるバッチファイルをWSLから起動しようとすると、全てエラーとなってしまう(もしくはLinuxのシェルで解釈されてしまう)。前述の通り、これらの内部コマンドには、「cmd /c 〜」と書き直さないと、Windowsのコマンドとして認識されないためだ。
しかし、いちいち直すのは面倒である。そこで、WSLからバッチファイルを呼び出したい場合は、「cmd.exe /c mybatch」のように、バッチファイルそのものを「cmd.exe /c 〜」で実行するとよい。
Windowsのパスに含まれる特殊文字に注意
WSLとWindows OSではパス名の表記方法が異なるので、WSL(Linux)のパス指定をそのままWindows OSのコマンドプロンプト側へ渡してもエラーになる。事前にWindows OSのパス表記に変更する必要があるが、空白文字や(パス区切りの)バックスラッシュ(\)が含まれている場合は全体を引用符で囲む。
パスに含まれる特殊文字に注意
Windowsのファイルシステムでは空白文字やバックスラッシュなどの特殊な文字が使われていることが多い。WSL表記からWindows表示へ変換するとともに、全体を引用符で囲んで引数とする。
WSLのパス形式とWindowsのパス形式を相互に変換するには、WSL用のwslpathコマンドが利用できる。wslpathコマンドについてはTIPS「Windows 10のコマンドプロンプトからWSL上のLinuxコマンドを呼び出す」を参照のこと。
なお、WSLから呼び出されたコマンドは、カレントドライブは「C:」、カレントフォルダは「\Windows\System32」という状態で起動する。そのため、ファイル名などをパラメータとして渡す場合は、常にフルパス名で渡すのがよい。
Windowsコマンドの起動パス
WSLから呼び出されたコマンドは、「C:\Windows\System32」がカレントフォルダに設定された状態で実行されるようである。パス名などを引数として渡す場合は、カレントフォルダの場所がどこであっても問題ないように、フルパスにすることが望ましい。
Windows側コマンドはコードページ=65001(UTF-8)の環境で実行される
TIPS「Windows 10のコマンドプロンプトからWSL上のLinuxコマンドを呼び出す」でも述べているように、WSL環境では、文字コードは「UTF-8(コードページ=65001)」としてプログラムが実行されている。
しかし日本語Windows OSのコマンドプロンプトでは、デフォルトの文字コードはShift_JIS(コードページ=932)となっている。なので、コマンドの実行結果に日本語文字が含まれる場合は、注意が必要である(次の記事も参照)。コマンド側の出力がShift_JISなら、WSL側で受け取った後、UTF-8に変換するなどの対策を行う必要があるだろう。Windows OSに標準で付属するコマンドは、コードページ設定に応じて適切な文字コードにして出力するものが多いが(日本語Shift_JISメッセージと英語メッセージを切り替えるだけだが)、そうでないコマンドも多数ある(このあたりは、実際にやってみて適宜対応するしかない)。
- Windows 10 Latest「Windows 10に搭載されたLinuxサブシステムにおける、Windowsプログラムとの連携や日本語処理機能を検証する」
文字コードに注意
日本語WindowsではShift_JISを使っているが、WSL側から呼び出された場合はUTF-8になっている。なので、テキストデータを受け渡したり、バッチ中で日本語を使ったりする場合は、UTF-8にしたり、文字コード変換をしたりすること。
※nkfは漢字コードを変換するツール(こちらのTIPSを参照)。Ubuntuなら、「apt update」「apt intall nkf」の手順でインストールできる。
なおコマンドプロンプト側で起動するバッチ中で、日本語文字列をShift_JISで記述していると(例えば「echo 日本語です」を実行するバッチファイルをShift_JISで記述しておくと)、WSLから呼び出した場合に文字化けしてしまう(UTF-8環境で実行されるため)。どうしてもWSL側から呼び出したければ、バッチファイルをUTF-8環境向けに作り直したり、日本語メッセージを使わないバッチにしたりする、などの対策が必要である。
Copyright© Digital Advantage Corp. All Rights Reserved.