LoginSignup
8
5

More than 5 years have passed since last update.

PowerShell で which コマンドを作る

Last updated at Posted at 2018-01-31

msys2 等でインストールしたり where.exe を使う方法もありますが、PowerShell だけでできる方法にします。

こちらの記事を参考にしました。

ファイルのパスを取得する方法

Get-Command で返ってくる Definition あるいは Source プロパティにファイルのパスが含まれています。
ですが、 Source プロパティよりも Definition プロパティの方が汎用性が高いので、こちらを使います。

Get-member をしてみると、

PS> gcm pwsh | gm

   TypeName: System.Management.Automation.ApplicationInfo

Name               MemberType     Definition
----               ----------     ----------
Equals             Method         bool Equals(System.Object obj)
GetHashCode        Method         int GetHashCode()
GetType            Method         type GetType()
ResolveParameter   Method         System.Management.Automation.ParameterMetadata ResolveParameter(string name)
ToString           Method         string ToString()
CommandType        Property       System.Management.Automation.CommandTypes CommandType {get;}
Definition         Property       string Definition {get;}
Extension          Property       string Extension {get;}
Module             Property       psmoduleinfo Module {get;}
ModuleName         Property       string ModuleName {get;}
Name               Property       string Name {get;}
OutputType         Property       System.Collections.ObjectModel.ReadOnlyCollection[System.Management.Automation.PST... Parameters         Property       System.Collections.Generic.Dictionary[string,System.Management.Automation.Paramete... ParameterSets      Property       System.Collections.ObjectModel.ReadOnlyCollection[System.Management.Automation.Com... Path               Property       string Path {get;}
RemotingCapability Property       System.Management.Automation.RemotingCapability RemotingCapability {get;}
Source             Property       string Source {get;}
Version            Property       version Version {get;}
Visibility         Property       System.Management.Automation.SessionStateEntryVisibility Visibility {get;set;}
FileVersionInfo    ScriptProperty System.Object FileVersionInfo {get=[System.Diagnostics.FileVersionInfo]::getversio... HelpUri            ScriptProperty System.Object HelpUri {get=$oldProgressPreference = $ProgressPreference...

これだけのものが出てきますが、欲しい情報は Definition だけです。
それだけを取り出す方法はいくつかあり、上の記事で紹介されている (gcm $command).Definition 以外にも

PS > (gcm pwsh).Definition
C:\Program Files\PowerShell\6.0.0\pwsh.exe
PS> gcm pwsh | fl -p Definition


Definition : C:\Program Files\PowerShell\6.0.0\pwsh.exe


PS> gcm pwsh | select -p Definition

Definition
----------
C:\Program Files\PowerShell\6.0.0\pwsh.exe

などがあります。
それぞれ表示が違うので好みで使い分けてください。
上の記事で紹介されていた Format-List もオプションで -Property Definition と指定すれば Definition だけを取り出せます。

コマンドとして使える様にする

意味合い的には Select-Object -Property Definition が一番妥当だと思うのですが、 Select-Object では表示されず Format-List では表示されるものもあるので、 Format-List を使ってコマンド化します。
といっても簡単で、

function which ($command) {
    Get-command -Name $command -ShowCommandInfo | Format-List -Property Definition
}

これで完了です。

これを毎回使える様にするために、このファンクションを $PROFILE に書きましょう。

$PROFILE には4種類あり、

PS> $PROFILE | gm -m NoteProperty | select -p Name, MemberType

Name                     MemberType
----                     ----------
AllUsersAllHosts       NoteProperty
AllUsersCurrentHost    NoteProperty
CurrentUserAllHosts    NoteProperty
CurrentUserCurrentHost NoteProperty

AllUsersCurrentUser かはその名の通り、 AllHostsCurrentHost かはちゃんと分かっていませんが、
PowerShell で CurrentHost に設定した場合 PowerShell ISE には適用されません。
個人で使っている範囲で、PowerShell にも ISE にも適用して欲しいのであれば、 CurrentUserAllHosts に書くのが良いでしょう。

# ディレクトリやファイルが無い場合、ファイルを作成
PS> $profilePath = Split-Path -Path $PROFILE.CurrentUserAllHosts -Parent
PS> $profileName = Split-Path -Path $PROFILE.CurrentUserAllHosts -Leaf
PS> mkdir $profilePath
PS> ni -Path $profilePath -Name $profileName
# 既定のエディタで開く
PS> ii $PROFILE.CurrentUserAllHosts
# ファンクションを書いて保存したら読み込む
PS> . $PROFILE.CurrentUserAllHosts

これで PowerShell で which コマンドのようなものが使える様になりました。

おまけ

  1. 上で

    Source プロパティよりも Definition プロパティの方が汎用性が高い

    と言ったのは pwsh(.exe) のようにファイルのものではどちらでも変わりませんが、例えばファンクションやエイリアス、コマンドレットでは

    PS > gcm which | fl -Property Source
    
    Source :
    
    PS > gcm gcm | fl -Property Source
    
    Source :
    
    PS > gcm which | fl -Property Definition
    
    Definition : param($command)
    
                 Get-Command -Name $command -ShowCommandInfo | Format-List -Property Definition
    
    PS > gcm gcm | fl -Property Definition
    
    Definition : Get-Command
    
    PS > gcm Get-Command | fl -Property Definition
    
    Definition :
                 Get-Command [[-ArgumentList] <Object[]>] [-Verb <string[]>] [-Noun <string[]>] [-Module <string[]>] [-FullyQualifiedModule <ModuleSpecification[]>] [-TotalCount <int>] [-Syntax] [-ShowCommandInfo] [-All] [-ListImported] [-ParameterName <string[]>] [-ParameterType <PSTypeName[]>] [<CommonParameters>]
    
                 Get-Command [[-Name] <string[]>] [[-ArgumentList] <Object[]>] [-Module <string[]>] [-FullyQualifiedModule<ModuleSpecification[]>] [-CommandType <CommandTypes>] [-TotalCount <int>] [-Syntax] [-ShowCommandInfo] [-All] [-ListImported] [-ParameterName <string[]>] [-ParameterType <PSTypeName[]>] [<CommonParameters>]
    
    

    と違いが出ます。

    このように which コマンドを定義しておけば、ファイルのパスを見つけたい時だけではなく、ファンクションの定義を確認したいとき例えば which mkdir やコマンドレットのオプションを確認したいとき Get-Help Get-Command の代わりに which Get-Command と使える様になります。

  2. 上で

    Select-Object では表示されず Format-List では表示されるものもある

    と書いた事について

    これも1つめと同じでファンクションやコマンドレットで差が出ます。 Definition の出力が複数行にわたる場合や長い場合 Select-Object では省略されます。

    PS > gcm which | select -p Definition
    
    Definition
    ----------
    param($command)...
    
    PS> gcm Get-Command | select -p Definition
    
    Definition
    ----------
    ...
    
8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5