前回は、引数のパスが存在するかどうかをTest-Pathコマンドレットを使って判断するスクリプトを作成した。前回の成果物「test-d.ps1」は次のとおりだ。

#!/usr/bin/env pwsh

Test-Path -Path $args[0]

このスクリプトは基本的に何も気の利いたことはしていない。ここから徐々に、スクリプトとして扱いやすいものになるように拡張していこう。

使い方を表示する

よくあるコマンドの挙動に、「引数やオプションが想定されているものと異なっている場合に使い方を表示する」というものがある。「usage: 」というキーワードと共に、使い方の簡単な説明が表示されるものだ。これを前回作ったスクリプトに追加してみよう。少なくとも引数にパスを指定してほしいのだから、引数が何もなかった場合にメッセージを出力するようにしてみよう。作成したのが次の「test-d_2.ps1」だ。

#!/usr/bin/env pwsh

if (0 -eq $args.Length) {
    Write-Host "usage: test-d_2.ps1 ディレクトリパス"
}

Test-Path -Path $args[0]

前回作ったスクリプトと、上記スクリプトを実行してみると、次のようになる。

実行サンプル

test-d_2.ps1のほうは、使い方を示すメッセージが出力されている点に注目しよう。

ただし、test-d_2.ps1もtest-d.ps1と同じようにエラーが出力されている。使い方を示すメッセージを表示しただけで、そのまま次の処理へ進んでいるためだ。メッセージを出力したら、スクリプトを終了するほうがよいだろう。

メッセージを出力したら終了する

今度は次のように、メッセージを出力した後で「exit」を実行してスクリプトを終了するように変更してみる(test-d_3.ps1)。

#!/usr/bin/env pwsh

if (0 -eq $args.Length) {
    Write-Host "usage: test-d_2.ps1 ディレクトリパス"
    exit
}

Test-Path -Path $args[0]

実行すると次のようになる。

実行サンプル

パスを指定しなかった場合にはそのままスクリプトが終了していることがわかる。まずはそれらしいスクリプト第一歩といったところだ。

returnとexitの違いは

先ほどのスクリプトでは、終了する方法として何も考えずに「exit」を使ったが、似たようなことは「return」でもできる。試しに、「return」を使ったものを用意してみよう(test-d_4.ps1)。

#!/usr/bin/env pwsh

if (0 -eq $args.Length) {
    Write-Host "usage: test-d_2.ps1 ディレクトリパス"
    return
}

Test-Path -Path $args[0]

実行すると次のようになる。

実行サンプル

「exit」も「return」も見た目は同じだ。「exit」と「return」は、今回使ったようなケースでは似た動作をする。しかし、この2つは明確に異なるものだ。まず、「exit」と「return」はそれぞれ言語キーワードであり、PowerShellに用意されている言語としての機能だ。説明は、以下のPowershellの公式製品ドキュメントにまとまっている。


違いがわかりやすいのは、次の説明ではないかと思う。

言語キーワード「exit」の説明

言語キーワード「return」の説明

かなりざっくりとまとめると、次のようになる。

  • exit - スクリプトを終了するときに使う
  • return - 関数から抜けるときに使う


つまり、今回のケースでは「exit」を使うほうが適切ということになる。

「return」は現在のスコープから抜ける処理を行うので、「関数から抜ける」ために使う。関数の外で実行した場合、そこがスクリプトのスコープであればスクリプトが終了するので「exit」を使ったのと同じ結果にはなる。ただし、今回のケースでは「スクリプトを終了する」という明確な目的があるので、最初から「exit」を使うほうが適切だ。

「exit」と「$LASTEXITCODE」

前掲の説明を読むとわかるが、「exit」は引数として終了コードを取ることができる。Windowsプラットフォームでは「[int]::MinValue」から「[int]::MaxValue」までの整数(-2147483648〜2147483647)、UNIXプラットフォームでは「[byte]::MinValue」から「[byte]::MaxValue」までの整数(0〜255)を取ることができる。数値以外のものを指定したときや、範囲外の整数が指定された場合には「0」が指定されたものとして処理される。

「exit」に渡された終了コードは、PowerShellでは$LASTEXITCODE変数でアクセスでき、Windowsコマンドシェルでは%ERRORLEVEL%環境変数でアクセスできる。

終了コードは慣例的にプログラムが成功裏に終了した場合には「0」が、そうでない場合にはそれ以外の値が設定されることが多い。今回追加した「exit」は正常ではない場合の終了だから、例えば「exit 1」として終了するようにしよう。次のようになる(test-d_5.ps1)。

#!/usr/bin/env pwsh

if (0 -eq $args.Length) {
    Write-Host "usage: test-d_2.ps1 ディレクトリパス"
    exit 1
}

Test-Path -Path $args[0]

実行結果は以下のとおりだ。test-d_5.ps1の場合だけ、終了コードが「1」になっていることを確認できる。

実行サンプル

今回は4行追加しただけだが、「使い方が違うときに使い方を表示すること」と「エラーとして処理を終了すること」は、スクリプトを書く上で重要な処理となる。整理してしまえば簡単だが、とても大切なコードだ。

参考