PowerShell Core 6.2の実験的機能

先日公開された「PowerShell Core 6.2」はユーザの要望に応えることを目的としたリリースで、ユーザから寄せられた使い勝手に関する機能の導入や、バグ修正などが行われている。

新機能が大々的に導入されたバージョンといったものではなかったが、実験的機能という位置づけでいくつか興味深い機能が追加されているので、今回はそうした機能を取り上げておこう。

実験的機能という位置づけであるためデフォルトでは有効化されていないのだが、設定を変更すれば試すことができる。突拍子もない機能ではないので、今後のバージョンではデフォルトで有効になるものがほとんどだろう。先行して試しておいても損はない。

コマンドレット名を推測する機能

PowerShell CoreはUNIXの多機能インタラクティブシェルほどは、ユーザに対して入力サポート機能を提供していない。今回実験的に追加された機能のひとつに、この部分を強化するというものがある。

たとえばGet-Commandというコマンドレットを、間違えてGet-Commondと入力したとする。これまでであればユーザには次のようなエラーメッセージが表示される。

間違ったコマンドレット名を入力したのでエラーが表示される

PS /Users/daichi> Get-Commond
Get-Commond : The term 'Get-Commond' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-Commond
+ ~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-Commond:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

PS /Users/daichi>

「Enable-ExperimentalFeature -Name PSCommandNotFoundSuggestion」というコマンドレットを実行してから一旦PowerShell Coreを終了し、再度PowerShell Coreを実行する。こうすると、次のように動作が変わることを確認できる。

PowerShell Core側から、修正後コマンドレット名候補が提示される

 /Users/daichi> Enable-ExperimentalFeature -Name PSCommandNotFoundSuggestion
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.
PS /Users/daichi> exit
/Users/daichi$ pwsh
PowerShell 6.2.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /Users/daichi> Get-Commond
Get-Commond : The term 'Get-Commond' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-Commond
+ ~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Get-Commond:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException


Suggestion [4,General]: The most similar commands are: Get-Command, Get-Content, Set-Content, Get-TimeZone, Find-Command.
PS /Users/daichi>

PowerShell Core側が、Get-Commondという誤った入力に対してGet-Command、Get-Content、Set-Content、Get-TimeZone、Find-Commandという修正候補を表示していることがわかる。

PowerShell Coreではコマンドレット名や関数名に一定の規則があり、ある程度名前から機能が想像できるようになっているし、使いたい機能からも名前を推測できるようになっている。しかし、ともかく名前が長くなりがちで、直接タイピングすると誤りやすいもの事実だ。

この機能が有効になると、本来はどういったコマンドレット名を入力しようとしていたのかを確認することができるし、似たような名前のコマンドレットの確認もできる。早くデフォルトの機能になって欲しいところだ。

汎用的に使える一時ディレクトリ

WindowsであれmacOSであれLinuxであれ、一時ファイルなどを作成するためのディレクトリが用意されている。スクリプトなどを組む場合にはこうした場所を利用することになるのだが、PowerShell Coreではプラットフォームに応じて一時ディレクトリの場所をユーザが判別する必要があった。

今回、実験的機能としてTemp:というドライブが導入された。このドライブはプラットフォームごとの一時ファイル用ディレクトリに展開されることになり、ユーザはプラットフォームを気にすることなく一時ディレクトリを利用できるようになる。

機能が有効になっていない段階では、次のようにTemp:にアクセスしようとしてもエラーになる。

Temp:ドライブが有効になっていない状況

PS /Users/daichi> "Hello World!" > Temp:/hello.txt
out-file : Cannot find drive. A drive with the name 'Temp' does not exist.
At line:1 char:1
+ "Hello World!" > Temp:/hello.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (Temp:String) [Out-File], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.OutFileCommand

PS /Users/daichi>

「Enable-ExperimentalFeature -Name PSTempDrive」のように実行して一時ドライブを有効にすれば、次のようにTemp:がパスとして有効になる。

Temp:ドライブが有効になっている状況

PS /Users/daichi> Enable-ExperimentalFeature -Name PSTempDrive
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.
PS /Users/daichi> exit
/Users/daichi$ pwsh
PowerShell 6.2.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /Users/daichi> "Hello World!" > Temp:/hello.txt
PS /Users/daichi> Get-Content Temp:/hello.txt
Hello World!
PS /Users/daichi>

これもとても便利な機能だ。スクリプトを書いて処理をさせるということになってくると、一時ファイルの作成は欠かせないものになってくる。このようにプラットフォームに依存しない形で一時ファイルを簡単に用意できると作業効率が全然違う。こちらも早くデフォルトの機能になってもらいたい。

短縮名からのタブ展開

PowerShell Coreの最大の特徴であり、利点でありながらも欠点であるという、「コマンドレット名や関数名が長い」という点に対するMicrosoftの回答のひとつが、今回のバージョンに実験的機能として取り込まれた短縮名からの名前展開機能だ。

たとえば、次のようにi-arsavsfと実行すれば、当然こんな名前のコマンドは存在しないのでエラーとなる。

i-arsavsfは存在しないコマンドなので実行しようとしてもエラーとなる

 /Users/daichi> i-arsavsf
i-arsavsf : The term 'i-arsavsf' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ i-arsavsf
+ ~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (i-arsavsf:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

PS /Users/daichi>

ここで「Enable-ExperimentalFeature -Name PSUseAbbreviationExpansion」として短縮名展開機能を有効にしてあげると、i-arsavsfという短縮名を入力したあとでタブキーを押すことで……

この段階で短縮名のあとでタブキーを押す

 /Users/daichi> Enable-ExperimentalFeature -Name PSUseAbbreviationExpansion
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.
PS /Users/daichi>
PS /Users/daichi> exit
/Users/daichi$ pwsh
PowerShell 6.2.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /Users/daichi> i-arsavsf

次のように正規の名前に展開されるようになる。

タブキーを押したあとで正規のコマンドレット名に展開される

PS /Users/daichi> Enable-ExperimentalFeature -Name PSUseAbbreviationExpansion
WARNING: Enabling and disabling experimental features do not take effect until next start of PowerShell.
PS /Users/daichi>
PS /Users/daichi> exit
/Users/daichi$ pwsh
PowerShell 6.2.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /Users/daichi> Import-AzRecoveryServicesAsrVaultSettingsFile

現在のところ、Azure PowerShell Azモジュールがインストールされている場合にのみ機能するのだが、長い名前のコマンドレットを使う場合に便利なので、ぜひこの機能も有効になってほしいところだ。

ただし、この機能はインタラクティブにタブを入力したときに機能するものであってエイリアスとは異なる。スクリプトなどに短縮名を書いても機能しないし、タブで展開させないとやっぱりエラーになる。あくまでもインタラクティブに使用する場合に使い勝手を向上させるものだということを覚えておいてもらえればと思う。

参考資料