晴耕雨読

working in the fields on fine days and reading books on rainy days

[PowerShell] Linuxのwhichコマンドを作る

zshのwhichコマンドは、コマンドの場所や関数・エイリアスの定義を調べることができます。 zshのwhichのように、PowerShellにはGet-Commandがありますが、これをwhichで呼び出せるようにして、PowerShellでwhichコマンドが実行できるようにします。

結論から言うと、以下のコードを profile ファイルに書いてあげることで、起動時に which が使えるようになります。 なお、profile ファイルの場所は次のパスです。 %USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

function which($cmdname) {
  Get-Command $cmdname | Select-Object -ExpandProperty Definition
}

動きについて説明すると、まず Get-Command は実行すると次のようになります。 以下よりCommandTypeにはコマンドの種類が格納され、Nameにはコマンドの本名が格納されることが確認できます。

エイリアスを指定したとき:

PS> Get-Command ls

CommandType     Name                            Version    Source
-----------     ----                            -------    ------
Alias           ls -> Get-ChildItem

実行ファイルを指定したとき:

PS> Get-Command notepad

CommandType     Name                            Version    Source
-----------     ----                            -------    ------
Application     notepad.exe                     10.0.19... C:\Windows\system32\notepad.exe

Format-Listを使うことで、Table形式では表示されなかった値も表示することができます。 エイリアスのlsと実行ファイルのnotepadを指定したそれぞれの結果を以下に示します。

PS> Get-Command ls | Format-List

DisplayName       : ls -> Get-ChildItem
CommandType       : Alias
Definition        : Get-ChildItem
ReferencedCommand : Get-ChildItem
ResolvedCommand   : Get-ChildItem
> Get-Command notepad | Format-List

Name            : notepad.exe
CommandType     : Application
Definition      : C:\Windows\system32\notepad.exe
Extension       : .exe
Path            : C:\Windows\system32\notepad.exe
FileVersionInfo : File:             C:\Windows\system32\notepad.exe
                  InternalName:     Notepad
                  OriginalFilename: NOTEPAD.EXE.MUI
                  FileVersion:      10.0.19041.800 (WinBuild.160101.0800)
                  FileDescription:  メモ帳
                  Product:          Microsoft® Windows® Operating System
                  ProductVersion:   10.0.19041.800
                  Debug:            False
                  Patched:          False
                  PreRelease:       False
                  PrivateBuild:     False
                  SpecialBuild:     False
                  Language:         日本語 (日本)

表示させたい一番重要な部分は Definition なので、Select-Object でプロパティのフィルターをしてから出力するようにコマンドレットを組み立てていけば、疑似whichコマンドの完成です。

> Get-Command notepad | Select-Object -Property Definition

Definition
----------
C:\Windows\system32\notepad.exe

Select時に -Property の代わりに -ExpandProperty を使うことで、テーブル形式ではなく文字列で表示するようになります。

> Get-Command notepad | Select-Object -ExpandProperty Definition
C:\Windows\system32\notepad.exe

最後にここまでの内容でwhichコマンドを関数にします。

function which($cmdname) {
  Get-Command $cmdname -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition
}

指定したコマンドが存在しない場合はエラーを表示しないように -ErrorAction SilentlyContinue を加えて実際のwhichコマンドと同じになるようにしています。

which関数の使い方は以下の通りです。なお、which関数自身の詳細も表示できます。

PS> which ls
Get-ChildItem
PS> which notepad
C:\Windows\system32\notepad.exe
PS> which which
param($cmdname)

  Get-Command $cmdname -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Definition

以上です。

参考文献