Test-Path Cmdletを使用したPowerShell:ファイル、キーなどの検証

ファイル、レジストリキー、証明書、またはその他のPowerShellドライブパスのパスを検証する必要がある場合、Test-Pathコマンドレットが必要です。

Test-Pathコマンドレットは、ファイルやその他のアイテムの多くの属性を簡単にチェックするための便利な方法です。ファイルが存在するかどうか(または他のアイテムタイプ)、文字列が適切なパス形式であるかどうか、特定の時間より新しいか古いかどうかをチェックすることができます。

このチュートリアルでは、PowerShellのTest-Pathコマンドレットについて詳しく説明し、PowerShellスクリプトを改善するためにどのように使用できるかを学びます。

前提条件

このチュートリアルの例に従いたい場合、PowerShellが必要です。具体的には、Windows 10でPowerShell v7.03を使用しますが、学ぶテクニックの多くは古いバージョンにも適用されます。

Test-Pathコマンドレットは何をするのか?

PowerShellのTest-Pathコマンドレットは、非常にシンプルなコマンドの1つです。このコマンドはPowerShellの最初から存在しており、TrueまたはFalseの2つの値のみを返します。

しかし、そのシンプルさに惑わされないでください。PowerShellスクリプトで情報を検証する際に、大いに時間を節約することができます。

PowerShellのTest-Pathコマンドレットは、PowerShellプロバイダーやドライブを使用する際の品質管理と考えてください。スクリプトを作成する際、一般的にはPowerShellドライブに含まれるさまざまなアイテムと共に作業します。例えば、C:\, HKLM、CertなどのPowerShellドライブを使用します。

Test-PathはすべてのPSドライブで動作しません。例えば、レジストリキーに対してTest-Pathを使用しようとすると、動作します。しかし、レジストリ値に対してTest-Pathを使用しようとすると、常にFalseが返されます。

もし興味があるならば、今すぐPowerShellでGet-PSDriveコマンドレットを実行し、表示されるすべてのPSドライブを確認してください。

PS Drives after running Get-PSDrive

これらのドライブは、C:\WindowsHKLM:\Softwareなどのように内部にパスを持っています。PowerShellスクリプト内でパスを使用する際には、まずそのパスが有効か存在するかどうかをテストすることが常に良いプラクティスです。これがPowerShellのTest-Pathが行う役割です。

Test-Pathは、特定の条件が満たされたかどうか(通常はファイル/フォルダ、レジストリキー、証明書、または変数が存在するかどうか)に応じてTrueまたはFalseを返す条件を定義します。

Test-Pathのパラメータと使用法

Test-Pathコマンドレットは、他の多くのPowerShellコマンドレットと同様に、動作を変更するさまざまなパラメータを持っています。次に、各パラメータについて説明し、その動作と期待される結果をデモンストレーションします。

Path

Pathパラメータは、Test-Pathの実行ごとに使用する必須のパラメータです。このパラメータは、存在をテストしたいPSDriveのパスを定義します。

たとえば、フォルダC:\Fooが存在するかどうかをテストしたい場合は、適切なパスをPathパラメータに指定します。その後、C:\Fooが実際に存在するかどうかに応じて、Test-PathTrueまたはFalseを返します。

PS> Test-Path -Path 'C:\Foo'
True

同じテクニックは、他のアイテムのパスにも使用できます。たとえば、レジストリキーHKLM:\Software\Fooが存在するかどうかをテストしたい場合は、レジストリキーパスをPathパラメータに使用します。

PS> Test-Path -Path 'HKLM:\Software\Foo'
True

このチュートリアルでデモンストレーションされるすべてのテクニックは、任意のPowerShellドライブパスで動作します。

ワイルドカードの使用

もしもパスが特定の値と一致するかどうかを気にしない場合、代わりにパスが特定のパターンに一致するかどうかをチェックしたい場合は、ワイルドカードをPathの値で使用することができます。

たとえば、C:\Fooフォルダに、Barで始まるサブフォルダが含まれているかどうかをチェックしたい場合、ワイルドカードを使用することができます。

PS> Test-Path -Path 'C:\Foo\Bar*'

上記のコマンドを実行すると、Test-Path任意のフォルダが Bar で始まるかどうかを確認し、その条件に一致するフォルダが存在するかどうかに応じて True または False を返します。

アスタリスク(*)は一文字以上の任意の文字に一致しますが、疑問符(?)も使用してより詳細に一文字だけに一致するかテストすることができます。

上記のシナリオを例にすると、フォルダ C:\Foo\Bar1 が存在する場合、以下のコマンドを使用して Foo の任意のサブフォルダで Bar で始まり、正確に4文字のフォルダをテストすることができます。

PS> Test-Path -Path 'C:\Foo\Bar?'

何らかの理由で、ワイルドカードを使用したいが、ワイルドカード文字(*)を文字通りにマッチさせたい場合は、バッククォート(`)を使ってワイルドカード文字をエスケープすることができます。

LiteralPath

LiteralPath パラメータは Path パラメータとほぼ同じですが、ワイルドカードは許可されません。 LiteralPath を使用すると、パスの値が 文字通り 解釈されます。

たとえば、LiteralPath を使用してパスの値にアスタリスクや疑問符を含めようとすると、Test-Path はワイルドカード文字を完全に無視し、以下の例のように文字通りに C:\Foo\Bar? をテストします。

PS> Test-Path -LiteralPath 'C:\Foo\Bar?'

Test-Path が期待するパスを正確にテストするためにワイルドカード文字を使用する必要がない場合は、デフォルトのパスパラメータとして LiteralPath を使用する必要があります。

PathType

デフォルトでは、Test-Pathを実行し、パスを指定すると、そのパス内で何かを見つけた場合にTrueを返します。パスには、ファイルフォルダ、レジストリキー、証明書ストアなどのコンテナや、ファイル、レジストリ値、証明書などのリーフなどが含まれます。

PathTypeパラメータを使用して、Test-Pathをより詳細に設定し、コンテナまたはリーフのアイテムを特定してテストすることもできます。

Test-Pathは、デフォルトでPathTypeAnyを使用します。

たとえば、C:\Foo\Barにフォルダがあり、そのパスでファイルを検索している場合、以下に示すようにPathTypeパラメータを使用することができます。存在するかどうかだけを確認するには、C:\Foo\Barという名前のファイルが存在するかどうかをチェックします。

PS> Test-Path -LiteralPath 'C:\Foo\Bar' -PathType Leaf

また、C:\Foo\Barが実際にファイルかどうかを確認する必要がある場合は、コンテナをチェックします。

PS> Test-Path -LiteralPath 'C:\Foo\Bar' -PathType Container

含む

Pathパラメータとワイルドカードを使用する場合、より具体的な情報が必要な場合があります。その場合は、IncludeおよびExcludeパラメータを調べる必要があります。

次のようなフォルダがあるとします。

  • C:\Foo\Bar1
  • C:\Foo\Bar2
  • C:\Foo\Bar3

Barで始まる4文字のフォルダが存在するかどうかを確認したい場合、Bar1Bar2などが該当します。

PS> Test-Path -Path C:\Foo\Bar? -PathType Container

上記のコマンドは正常に動作しますが、C:\FooにあるBar2という名前のフォルダのみを検索したい場合は、Includeパラメータを使用できます。

PS> Test-Path -Path C:\Foo\Bar? -PathType Container -Include 'Bar2'

上記のコマンドは、基本的に単一のフォルダC:\Foo\Bar2のテストのみを行います。おそらく、Test-Path -Path 'C:\Foo\Bar2' -PathType Containerを使用する方が良いでしょう。

除外する

Excludeパラメータは、Includeパラメータと同様に機能しますが、この場合は一致するパスを除外します。

おそらく、C:\Fooフォルダ内に少なくとも1つのファイルが存在することを確認したい場合、次のコマンドを使用します:

PS> Test-Path -Path C:\Foo\* -PathType Leaf

上記のコマンドは、C:\Foo内にファイルがあるかどうかを示すTrueまたはFalseを返します。ただし、txt拡張子のファイル以外のすべてのファイルが存在することを確認したい場合、Excludeパラメータを使用して、txt拡張子のファイルをテストから除外するワイルドカードを使用することができます。

PS> Test-Path -Path C:\Foo\* -PathType Leaf -Exclude *.txt

フィルター

Microsoftのドキュメントによると、Filterパラメータは、「プロバイダの形式または言語のフィルタを指定します。このパラメータの値はPathパラメータとして修飾されます。フィルタの構文(ワイルドカード文字の使用を含む)は、プロバイダによって異なります」とされています。

Filterパラメータは、Get-Childitemなどの他のcmdletと共に使用する必要があるはずですが、Test-Pathと一緒に使用することはほとんどありません。もしFilterパラメータの良い使い方を見つけた場合は、Twitterの@adbertramまでお問い合わせください。

関連: Get-ChildItem: ファイル、レジストリ、証明書などを1つのリストとして表示する

NewerThan

ファイルのタイムスタンプを確認し、それに基づいて判断する必要があったことはありますか?もしそうなら、NewerThanパラメータとOlderThanパラメータがたくさんのコードを節約してくれます。NewerThanパラメータは、アイテムのタイムスタンプが特定の日付より新しいかどうかを確認します。

NewerThanパラメータは、タイムスタンプを確認するために文字列またはDateTimeオブジェクトを受け入れます。たとえば、ファイルC:\Foo\bar.txtが2021年1月20日以降に作成されたかどうかを確認するには、次のようにTest-Pathを実行します。

Test-Path -LiteralPath 'C:\Foo\bar.txt' -NewerThan 'January 20, 2021'
## または
Test-Path -LiteralPath 'C:\Foo\bar.txt' -NewerThan '1/20/21'

OlderThan

OlderThanパラメータは、NewerThanパラメータとまったく同じですが、逆の動作をします。このパラメータは、アイテムが特定の日付よりも古いかどうかを確認します。

Test-Path -LiteralPath 'C:\Foo\bar.txt' -OlderThan 'January 20, 2021'
## または
Test-Path -LiteralPath 'C:\Foo\bar.txt' -OlderThan '1/20/21'

IsValid

スクリプトで動的にパスを構築したことがある場合、その苦労はわかるでしょう。パスにキーを誤って入力したり、特殊文字をパスに含めたりすることがありますが、そのような場合にはIsValidパラメータが役立ちます。

IsValidパラメータは、Test-Pathを存在確認のためのコマンドレットではなく、パスの構文を確認するコマンドレットに変えます。このパラメータは、パスが有効かどうかを確認します。ただし、存在の有無は確認しません

例えば、パスが構文的に有効かどうかを検証する必要があるかもしれません。いくつかの変数を使用してパスを構築する場合は、常にJoin-Pathコマンドレットを使用してください。これは単なる例です!

パスを連結する場合は、常にJoin-Pathコマンドレットを使用してください。これは単なる例です!

$someVar = 'abc:dff'
$rootPath = 'C:\'
$path = "$someVar$rootPath

動的に作成されたパスが有効であることを確認するには、以下のようにIsValidパラメータを使用します。すると、Test-PathFalseを返すことがわかります。

PS> Test-Path -LiteralPath $path -IsValid
False

パスabc:dffC:\は無効なパスです。これにより、この状況から検証ルーチンを作成できます。

PowerShell v6.1.2以前を使用し、IsValidパラメータとPathTypeパラメータを一緒に使用している場合、Test-PathPathTypeパラメータを無視します。

資格情報

Test-PathCredentialパラメータがあるかもしれませんが、別のユーザーとしてPSドライブに認証するために使用できると思うかもしれません。それは正しい仮定ですが、実際には違います。

残念ながら、Test-PathコマンドレットではCredentialパラメータはほとんど機能しません。代わりに、マイクロソフトはInvoke-Commandコマンドレットを使用し、そこでCredentialパラメータを使用することをお勧めしています。

Invoke-Command -Credential (Get-Credential) -Scriptblock {Test-Path -LiteralPath 'C:\'}

関連記事: Invoke-Command: リモートコードを実行する最良の方法

Source:
https://adamtheautomator.com/powershell-test-path/