前回までで、PowerShellスクリプトがかなり仕上がってきた。今回は、PowerShellに用意されている機能を使ってさらにPowerShell風のスクリプトに仕上げていこう。今回取り組むのは、Get-Help対応だ。
前回仕上げたスクリプト「test-d_13.ps1」は次の通りだ。引数の処理として「Param()」を使うように変更し、パラメータ指定時に補完機能が効くようになったことなどを確認した。
#!/usr/bin/env pwsh
#====================================================================
# 引数処理
#====================================================================
Param(
[string]$DirectoryPath,
[switch]$Help
)
if ($Help -Or -Not $DirectoryPath) {
$scriptname = Split-Path -Leaf $PSCommandPath
$errmsg = "usage: $scriptname " `
+ "[-DirectoryPath] ディレクトリパス " `
+ "[-Help]"
Write-Error $errmsg
exit 1
}
#====================================================================
# ディレクトリパスの存在確認処理
#====================================================================
if (Test-Path -PathType Container -Path $DirectoryPath) {
# 指定されたパスはディレクトリであり、存在している。
$True
} else {
# 指定されたパスはディレクトリではない。
if (Test-Path -PathType Leaf -Path $DirectoryPath) {
# 指定されたパスはファイル。
$infomsg = "$DirectoryPath : " `
+ "ファイルです。"
} else {
# 指定されたパスは存在しない。
$infomsg = "$DirectoryPath : " `
+ "そのようなディレクトリは存在しません。"
}
Write-Host $infomsg
$False
}
このスクリプトでは-Helpパラメータでスクリプトの簡単な使い方が表示されるようにしたわけだが、この書き方だとGet-Helpコマンドレットは次のように本当に最小限の出力しか行わない。
PowerShellでは、Get-Helpコマンドレットを使うことで、ほかのコマンドレットやモジュール、関数などのマニュアル(ヘルプ)を表示させることができる仕組みになっている。これはスクリプトにおいても同様で、「Get-Help」で使用できるようにヘルプを書いておけば、Get-Helpコマンドレットでもっときちんとした出力が行われるようになる。今回は、この部分の書き換えを行っていく。
「Get-Help」に対応したヘルプの書き方
スクリプトの場合、スクリプトが始まった直後に規定のフォーマットのコメントを書くことが「Get-Help」に対応する方法になっている。フォーマットは非常にシンプルなroffのようなもので、例えば次のように書けばよい。
<#
.SYNOPSIS
Adds a file name extension to a supplied name.
.DESCRIPTION
Adds a file name extension to a supplied name.
Takes any strings for the file name or extension.
.PARAMETER Name
Specifies the file name.
.PARAMETER Extension
Specifies the extension. "Txt" is the default.
.INPUTS
None. You cannot pipe objects to Add-Extension.
.OUTPUTS
System.String. Add-Extension returns a string with the extension
or file name.
.EXAMPLE
PS> extension -name "File"
File.txt
.EXAMPLE
PS> extension -name "File" -extension "doc"
File.doc
.EXAMPLE
PS> extension "File" "doc"
File.doc
.LINK
http://www.fabrikam.com/extension.html
.LINK
Set-Item
#>
上記サンプルは、次のドキュメントに掲載されているものだ。
基本的に「Get-Help」に対応したヘルプの書き方は上記のドキュメントにまとまっているので、これを参考にして書けばよい。
「.(ピリオド)」から始まっている大文字で記述された行は「キーワード」と呼ばれ、ヘルプで言うところの「セクションタイトル」に相当する。キーワードに続く行がそのセクションの内容だ。今作成しているスクリプトについて「Get-Help」に対応したコメントを書くとすれば、次のような感じになるだろう。
<#
.SYNOPSIS
ディレクトリパスが存在するかどうかを判定。
.DESCRIPTION
指定されたパスがディレクトリパスであり、かつ、存在するかどうかを判定する。
.PARAMETER DirectoryPath
ディレクトリパスを指定。
.PARAMETER Help
ヘルプメッセージを表示。
.INPUTS
なし。パイプには対応していない。
.OUTPUTS
System.Boolean。ディレクトリパスが存在する場合にTrue、そうでない場合にFalse。
.EXAMPLE
PS> .\test-d .\Documents\
True
.EXAMPLE
PS> .\test-d .\Documents-non-exists\
False
.LINK
Test-Path
#>
キーワードには次のようなものが用意されている。
キーワード | 内容 |
---|---|
.SYNOPSIS | スクリプトの簡単な説明。1回だけ使用可能 |
.DESCRIPTION | スクリプトの詳しい説明。1回だけ使用可能 |
.PARAMETER パラメータ名 | パラメータの説明 |
.EXAMPLE | サンプルを記述 |
.INPUTS | パイプラインで接続できるオブジェクトの.NET型 |
.OUTPUTS | 出力されるオブジェクトの.NET型 |
.NOTES | スクリプトの追加情報 |
.LINK | 関連するトピックやURI |
.FORWARDHELPTARGETNAME コマンド名 | 指定したコマンドのヘルプへリダイレクト |
.FORWARDHELPCATEGORY カテゴリ | Alias、Cmdlet、HelpFile、Function、Provider、General、FAQ、Glossary、ScriptCommand、ExternalScript、Filter、All |
.REMOTEHELPRUNSPACE PSSession値 | ヘルプトピックを含むセッションを指定 |
.EXTERNALHELP XMLヘルプファイル | XMLベースヘルプファイル |
表のキーワードは上のものほどよく使うもので、下にいくほどあまり使われないものになっている。「Get-Help」に対応したコメントはスクリプトの仕様書としても使えるものだ。スクリプトを書くときは最初にこのコメントを書き、その通りに動作するようにスクリプトを仕上げていくというのが書き方の一つにもなる。
「Get-Help」に対応させたスクリプト
では、「Get-Help」に対応させたスクリプトに書き換えてみよう。今回書き換えたスクリプト「test-d_14.ps1」は次の通りだ。
#!/usr/bin/env pwsh
<#
.SYNOPSIS
ディレクトリパスが存在するかどうかを判定。
.DESCRIPTION
指定されたパスがディレクトリパスであり、かつ、存在するかどうかを判定する。
.PARAMETER DirectoryPath
ディレクトリパスを指定。
.PARAMETER Help
ヘルプメッセージを表示。
.INPUTS
なし。パイプには対応していない。
.OUTPUTS
System.Boolean。ディレクトリパスが存在する場合にTrue、そうでない場合にFalse。
.EXAMPLE
PS> .\test-d .\Documents\
True
.EXAMPLE
PS> .\test-d .\Documents-non-exists\
False
.LINK
Test-Path
#>
#====================================================================
# 引数
#====================================================================
Param(
[string]$DirectoryPath, # ディレクトリを指定
[switch]$Help # ヘルプを表示
)
if ($Help -Or -Not $DirectoryPath) {
Get-Help $PSCommandPath
exit 1
}
#====================================================================
# ディレクトリパスの存在確認
#====================================================================
if (Test-Path -PathType Container -Path $DirectoryPath) {
# 指定されたパスはディレクトリであり、存在している。
$True
} else {
# 指定されたパスはディレクトリではない。
if (Test-Path -PathType Leaf -Path $DirectoryPath) {
# 指定されたパスはファイル。
$infomsg = "$DirectoryPath : " `
+ "ファイルです。"
} else {
# 指定されたパスは存在しない。
$infomsg = "$DirectoryPath : " `
+ "そのようなディレクトリは存在しません。"
}
Write-Host $infomsg
$False
}
まず、動作から見てみよう。-Helpパラメータを指定する、もしくは引数を何も指定しないと「Get-Help」が内部で呼ばれるようにしてあるため、次のようにヘルプが表示される。
直接「Get-Help」を使ってヘルプを表示させることもできる。先ほどと同じ出力が行われていることがわかるだろう。
「Get-Help」にパラメータを指定すれば、より詳細なヘルプを表示させることもできる。
「Get-Help」に対応したコメントを追加しただけではなく、次のように-Helpパラメータを処理する部分も書き換えた。前回は、次のように自前で出力するメッセージ(usage)を作成し、それをWrite-Errorコマンドレットで出力させていた。
$scriptname = Split-Path -Leaf $PSCommandPath
$errmsg = "usage: $scriptname " `
+ "[-DirectoryPath] ディレクトリパス " `
+ "[-Help]"
Write-Error $errmsg
今回は、この部分を次のように、内部でGet-Helpコマンドレットを呼ぶ処理へ変更している。
Get-Help $PSCommandPath
スクリプトが「Get-Help」による出力に対応したのだから、内部から自分を指定して「Get-Help」を実行すれば-Helpパラメータの処理として使えるというわけだ。その分コードは短くなるし、重複する説明を書く必要もなくなり、スマートである。
これまで何度も説明しているように、スクリプトの処理そのものは「Test-Path」で指定されたパスがディレクトリかどうかを判定しているだけだ。しかし、スクリプトとして使えるように、PowerShellの流儀に従って整理していくと、結構なボリュームになってくる。最初にこの辺りをしっかり理解しておけば、今後のスクリプト作成がぐっと楽になるので、今のうちにこういった書き方はマスターしてしまおう。