まず、前回作成したスクリプト「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]

引数を1つだけとり、指定されたパスが存在していた場合に「$True」を、存在していない場合に「$False」を返す。引数がなかった場合には使い方を示すメッセージを出力して、「exit 1」で終了する。この場合、「$LASTEXITCODE」には「1」が入ることになる。

このスクリプトは、「指定されたパスが存在するかどうか」しかチェックしていない。対象がディレクトリだろうがファイルだろうが、「$True」として判断してしまう。もともと作りたいと思っているのは、「指定されたディレクトリが存在するかどうか」を調べるスクリプトなので、このままだと問題がある。

ディレクトリとファイルは「Test-Path -PathType」で区別

指定されたパスが存在するかどうかを調べるTest-Pathコマンドレットだが、そのマニュアルを読むと、次のように「-PathType」というパラメータが用意されていることがわかる。

Test-Path (Microsoft.PowerShell.Management) - PowerShell | Microsoft Docs


指定できる値は「Any」「Container」「Leaf」だ。どういった動作になるのか、実際に使って確認してみよう。ショートカットも含めて確認すると、次のようになる。

「Test-Path -PathType」の動作確認サンプル

「Container」はディレクトリを、「Leaf」がファイルを意味していることがわかる。上記サンプルではディレクトリに対するショートカットに対しても使ってみているが、これはファイルとして判定されている。とりあえず、「Test-Path -PathType」を使うことで対象がディレクトリかそうでないかの判断はできそうだ。

ディレクトリだけを判定するように変更

「-PathType Container」を加えたスクリプトが次の「test-d_6.ps1」だ。

#!/usr/bin/env pwsh

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

Test-Path -PathType Container -Path $args[0]

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

実行サンプル

test-d_5.ps1はディレクトリもファイルも存在していれば「$True」としているが、test-d_6.ps1はディレクトリに対してのみ「$True」という判断をしていることがわかる。これで一歩正解へ近づいたわけだ。

「$False」だったときに原因をメッセージを出力

さっきの実行結果をもう一度見てみよう。存在しないパスを指定したときは「$False」になっている。これは正しい動作だ。

存在しないパスは「$False」になる

つまり、パスがファイルだった場合にも「$False」、パスが存在しない場合にも「$False」になる。どちらも挙動は期待通りではあるのだが、せっかくなので、「$False」の理由がわかるようにしたい。そこで、対象がファイルだったのか、それともパスがそもそも存在していなかったのか、条件を切り分けてメッセージを出力するように書き換えたのが次の「test-d_7.ps1」だ。

#!/usr/bin/env pwsh

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

if (Test-Path -PathType Container -Path $args[0]) {
    $True
} else {
    if (Test-Path -PathType Leaf -Path $args[0]) {
        Write-Host "$args[0]: ファイルです。"
    } else {
        Write-Host "$args[0]: そのようなディレクトリは存在しません。"
    }
    $False
}

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

実行サンプル

「$True」と「$False」が返ってくるのは先ほどと同じだが、「$False」だった場合にはその理由がメッセージとして表示されるようになった。だいぶスクリプトっぽい動きになってきた。

スクリプトが少し複雑になってきたので、コメントを書いておこう。今回の成果物「test-d_8.ps1」だ。

#!/usr/bin/env pwsh

# 1つの引数が必要。引数はディレクトリパス。
if (0 -eq $args.Length) {
    Write-Host "usage: test-d_2.ps1 ディレクトリパス"
    exit 1
}

if (Test-Path -PathType Container -Path $args[0]) {
    # 指定されたパスはディレクトリ
    $True
} else {
    # 指定されたパスはディレクトリではない
    if (Test-Path -PathType Leaf -Path $args[0]) {
        # 指定されたパスはファイル
        Write-Host "$args[0]: ファイルです。"
    } else {
        # 指定されたパスは存在しない
        Write-Host "$args[0]: そのようなディレクトリは存在しません。"
    }
    $False
}

ユーティリティ的に自分だけが使うようなスクリプトはそれほど複雑なものにしないほうが使い勝手が良いのだが、シンプルなスクリプトでも最低限のコメントは書いておくとよいと思う。

参考