PowerShell の date は Get-Date である


PowerShellにおいてエイリアスだと思っていたものがエイリアスではなかった件。

例えば、date と打ってみると、Linuxの date っぽい結果が得られる。

PS> date

2024年2月4日 5:49:56

PowerShellにおける date にあたるコマンドレットは、Get-Dateだ。

PS> Get-Date

2024年2月4日 5:49:56

では、dateGet-Date のエイリアスとして機能しているのか? Get-Alias コマンドレットで、登録済のエイリアスを確認してみる。

PS> Get-Alias

CommandType Name                         Version Source  
----------- ----                         ------- ------
# 省略
Alias       cp -> Copy-Item  
Alias       cpi -> Copy-Item  
Alias       cpp -> Copy-ItemProperty  
Alias       cvpa -> Convert-Path  
Alias       dbp -> Disable-PSBreakpoint  
Alias       del -> Remove-Item  
Alias       diff -> Compare-Object  
Alias       dir -> Get-ChildItem
# 省略

date というエイリアスは見当らない。

では、実は Get-Date コマンドレットではなく date.exe のような実行可能ファイルを呼んでいる可能性はないだろうか? Get-Command コマンドレットで確認してみる。

PS>  Get-Command date
Get-Command: The term 'date' is not recognized as a name of a cmdlet, function, script file, or executable program.  
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

違うらしい。

真相

date で呼び出されているのは Get-Date だった。 なぜエイリアスにない date という入力で呼び出すことができるかというと、コマンドレットのデフォルトの動詞が Get- だかららしい。 要するに、指定されたコマンドが見つからないとき、PowerShellは Get- を付けたコマンドが存在しないか探してみて、見つかったらそれを実行するようだ。

この挙動は、Get-Item を実行するとわかりやすく確認できる。

PS> item
  
cmdlet Get-Item at command pipeline position 1  
Supply values for the following parameters:  
Path[0]:

Get-Item は引数が必須であるため、引数なしで実行するとプロンプトが表示される。 実際に item と入力して実行してみると、"cmdlet Get-Item ..."と表示されており、Get-Item が呼ばれていることがわかる。

このような仕様なので、Get-Hoge 形式のコマンドレットは基本的に hoge で実行できる。 特に date uptime alias などは、Linuxでもお馴染のコマンドなので、一瞬その名前のコマンド(exe)が存在するのかと考えたくなるが、実際にはコマンドレットが実行されている。

それらしき箇所↓
PowerShell/src/System.Management.Automation/engine/CommandDiscovery.cs at 0919240822e032af91dc2fe4ce481e82002b92c0 · PowerShell/PowerShell · GitHub
CommandDiscovery.TryNormalSearch で、コマンド名に-\が含まれていない場合はGet-を付けてコマンドを探すようなことが書いてある。

例外

Get-Hogehoge 部分がPowerShellの予約語と衝突する場合は、例外となる。 例えば、Get-Process コマンドレットはここまでの説明に従えば process で呼べるように思えるが、"process"は予約語であるため、そちらが優先される。

また、help のケースでは Get-Help コマンドレットとは別に help という関数(Function)が存在しているため、単に help と打った場合、関数が実行され、Get- を補ってコマンドレットを探す挙動は発生しない。

Get- を補うのはあくまで補助的な挙動と理解したほうがよさそう。

参考