背景・目的・読み手
別記事でFindコマンドしたら上手く動かず、原因調査に一番時間がかかったので、今後も忘れないようにメモ。
読み手は主に自分と、同現象でハマってしまった方。
結論はこちら:上手く動く例
現象
コマンドプロンプトでは以下のようにFindコマンドが機能するのですが…。
C:\> systeminfo | find "Hyper"
[06]: Hyper-V Virtual Ethernet Adapter
Hyper-V の要件: ハイパーバイザーが検出されました。Hyper-V に必要な機能は表示されません。
何も考えずにPowerShellでこのコマンドを入力すると、以下のようにうまくいきません。
PS> systeminfo | find "Hyper"
FIND: パラメーターの書式が違います
原因
上手く動かない原因は2個あります。
1. 引用符 (") が消えてしまう
Findには引用符込みの引数を渡す必要がありますが、PowerShellにてコマンドに引用符を用いると展開可能な文字列として解釈されるらしく、結果引用符 (") が消えてしまうようです。
従って Find "Hyper"
は Find Hyper
のように解釈されます。Findは引用符で囲んだ文字列を検索文字列として必要とするため、ここでエラーとなります。
これを回避するために、Find '"Hyper"'
のようにシングルクォーテーションで両側を囲んでおくと Find "Hyper"
と解釈されます。
2. コンソールの文字コードと出力の文字コードの違い
上記の罠を突破したあとで、コマンドを入力すると出力結果が文字化けします。
PS> systeminfo | find '"Hyper"'
[06]: Hyper-V Virtual Ethernet Adapter
Hyper-V ???: ?????????????????Hyper-V ???????????????
これはパイプでデータを渡す際、デフォルトの設定がUS-ASCIIとなっていることが原因です1。これを回避するため、Findコマンドを実行する前に $OutputEncoding = [Text.Encoding]::Default
としておきます。
$OutputEncoding = [Text.Encoding]::Default
による設定変更はPowerShell実行の度にリセットされます。また、複数のPowerShellウィンドウを開いている場合は、それぞれで設定変更をする必要があります。
上手く動く例
上記2つの罠を回避するコマンド例はこちら:
PS> $OutputEncoding = [Text.Encoding]::Default
PS> systeminfo | find '"Hyper"'
[06]: Hyper-V Virtual Ethernet Adapter
Hyper-V の要件: ハイパーバイザーが検出されました。Hyper-V に必要な機能は表示されません。
余談
引数に半角スペースが含まれる場合は引用符が消えず、Findコマンドが上手く動くようです。なんでだろう…?
PS> $OutputEncoding = [Text.Encoding]::Default
PS> systeminfo | find "Hyper-V "
[06]: Hyper-V Virtual Ethernet Adapter
Hyper-V の要件: ハイパーバイザーが検出されました。Hyper-V に必要な機能は表示されません。
英語のみの環境で