PowerShell if not (否定) の使い方をサンプルコードで解説

PowerShellにおけるif not (否定) の使い方をサンプルコードで徹底解説

はじめに

PowerShellスクリプトを作成する上で、条件分岐は不可欠な要素です。特定の条件が満たされた場合にのみ処理を実行したり、条件に応じて異なる処理を選択したりすることで、スクリプトはより柔軟でインテリジェントな動作を実現します。PowerShellでの条件分岐といえば、まず思い浮かぶのがif文でしょう。

if文は、指定した「条件式」が真 ($true) と評価された場合に、それに続くスクリプトブロック内の処理を実行します。

“`powershell

基本的なif文の例

$variable = 15
if ($variable -gt 10) {
Write-Host “変数 variable は 10 より大きいです。”
}
“`

この例では、$variable -gt 10 という条件式が $true と評価されるため、Write-Host コマンドが実行されます。

しかし、スクリプトを作成していると、「この条件が満たされない場合に処理を実行したい」あるいは「この状態ではない場合に何かをしたい」といった、条件の否定が必要になる場面が頻繁にあります。ファイルが存在しない場合に作成する、特定のサービスが停止していない場合に警告を出す、特定のパターンに一致しない文字列をフィルタリングするなど、そのユースケースは多岐にわたります。

このような「条件の否定」をPowerShellのif文で表現する方法はいくつか存在します。本記事では、PowerShellにおけるif notとも言える、条件を否定してif文を記述するさまざまな方法について、それぞれの詳細、メリット・デメリット、そして豊富なサンプルコードを通じて、初心者から経験者までが深く理解できるように徹底的に解説します。

この記事を通じて、あなたはPowerShellで条件の否定を扱う際の最も効果的な方法を選択できるようになるでしょう。

PowerShellにおける真偽値 (Boolean) とは

if文の条件式は、最終的に真 ($true) または偽 ($false) という真偽値として評価されます。PowerShellでは、これらの真偽値を表すために予約変数 $true$false が用意されています。これらはSystem.Boolean型のインスタンスです。

“`powershell

真偽値の確認

$isTrue = $true
$isFalse = $false

Write-Host “Trueは $isTrue”
Write-Host “Falseは $isFalse”
Write-Host “IsTrueの型: $($isTrue.GetType().Name)”
Write-Host “IsFalseの型: $($isFalse.GetType().Name)”
“`

多くのコマンドレットや演算子は、結果として真偽値を返します。例えば、比較演算子 (-eq, -ne, -gt, -lt, -ge, -le, -like, -matchなど) の結果は真偽値です。

“`powershell

比較演算子の結果は真偽値

$a = 10
$b = 20

$result1 = ($a -lt $b) # 10 は 20 より小さい -> $true
$result2 = ($a -eq $b) # 10 は 20 と等しい -> $false

Write-Host “($a -lt $b) の評価結果: $result1”
Write-Host “($a -eq $b) の評価結果: $result2”
“`

また、特定の型の値は、条件式の中で使用された場合に暗黙的に真偽値に変換されます。この変換ルールを知っておくことは、「〜ではない場合」という条件を扱う上で非常に重要です。

  • 数値: 0$false と評価され、それ以外の数値は $true と評価されます。
  • 文字列: 空文字列 ("") は $false と評価され、それ以外の文字列は $true と評価されます。空白のみの文字列 (" ") は $true です。
  • 配列/コレクション: 要素を持たない空の配列やコレクションは $false と評価されません。要素が一つでも含まれていれば $true と評価されます。ただし、空のコレクションを直接 if ($collection) のように使用した場合の挙動は、PowerShellのバージョンやコレクションの性質によって微妙に異なる場合があるため、要素数 (.Count) でチェックする方が安全で一般的です。if ($collection.Count -eq 0) または if ($collection.Count -gt 0) のようにします。
  • $null: $null$false と評価されます。

“`powershell

暗黙的な真偽値変換の例

$numZero = 0
$numPositive = 10

$strEmpty = “”
$strHello = “Hello”

$arrayEmpty = @()
$arrayWithElements = @(1, 2)

$nullVariable = $null

Write-Host “0 は if 条件で $($numZero -as [bool]) と評価されます。”
Write-Host “10 は if 条件で $($numPositive -as [bool]) と評価されます。”
Write-Host “空文字列は if 条件で $($strEmpty -as [bool]) と評価されます。”
Write-Host “‘Hello’ は if 条件で $($strHello -as [bool]) と評価されます。”

配列の扱いは要注意(後述)

Write-Host “空配列は if 条件で $($arrayEmpty -as [bool]) と評価されます。” # PowerShell 7.x ではエラーにならないが、$false とは評価されないことが多い

Write-Host “$null は if 条件で $($nullVariable -as [bool]) と評価されます。”

配列の真偽値評価のより確実な方法

if ($arrayEmpty.Count -eq 0) { Write-Host “空配列は Count が 0 です。” }
if ($arrayWithElements.Count -gt 0) { Write-Host “要素を持つ配列は Count が 0 より大きいです。” }
“`

この真偽値への暗黙的な変換、特に $null や空文字列が $false と評価される特性は、後述する「-not 演算子を使った否定」や「変数やコマンドレットの結果を直接条件式に使う方法」で頻繁に利用されます。

否定演算子 -not (または !)

PowerShellで最も基本的な否定を表す演算子は -not です。これは、それに続く真偽値を反転させます。つまり、$true$false に、$false$true に変換します。

-not のエイリアスとして ! も使用できますが、スクリプトの可読性を考慮すると -not を使用するのが一般的です。本記事でも -not を使用して説明を進めます。

“`powershell

-not 演算子の基本

$isDaytime = $true
$isNighttime = -not $isDaytime # $isDaytime ($true) を否定 -> $false

Write-Host “昼間です: $isDaytime”
Write-Host “夜間です: $isNighttime”

$isFileProcessed = $false
$isFileNotProcessed = -not $isFileProcessed # $isFileProcessed ($false) を否定 -> $true

Write-Host “ファイルは処理されました: $isFileProcessed”
Write-Host “ファイルは処理されていません: $isFileNotProcessed”
“`

-not 演算子は、真偽値を返す任意の式やコマンドレットの結果に適用できます。これは if 文の条件式で条件全体を否定する際によく使用されます。

if文での条件の否定(if not)の様々な方法

それでは、if文で条件を否定する具体的な方法を見ていきましょう。主に以下の3つのアプローチがあります。

  1. -not 演算子を条件式全体に適用する
  2. 条件式の中で否定形の比較演算子を使用する
  3. コマンドレットの出力や変数の暗黙的な真偽値評価を利用・否定する

これらの方法をそれぞれ詳しく見ていきます。

方法1: -not 演算子を条件式全体に適用する

これは最も直接的で、様々な条件式に適用できる汎用的な方法です。if文の条件式の部分全体を括弧で囲み、その前に -not 演算子を置きます。

構文は以下のようになります。

powershell
if (-not (条件式)) {
# 条件式が $false と評価された場合に実行される処理
}

詳細な解説とサンプルコード:

この方法の利点は、元の肯定形の条件式をそのまま利用できる点です。肯定形の条件式がすでに明確に定義されている場合に、「その条件が満たされないとき」というのをシンプルに表現できます。

例1: ファイルが存在しない場合

Test-Path コマンドレットは、指定したパスが存在すれば $true、存在しなければ $false を返します。ファイルが存在しないという条件は、Test-Path の結果が $false であることと同義です。

“`powershell

例1: ファイルが存在しない場合にファイルを作成する

$filePath = “C:\Temp\myconfig.txt”

ファイルが存在しないかチェック

if (-not (Test-Path $filePath)) {
Write-Host “ファイル ‘$filePath’ は存在しません。作成します…”
# ファイルを作成する処理 (例: 空ファイルを作成)
New-Item -Path $filePath -ItemType File | Out-Null # 出力は不要なので Out-Null
Write-Host “ファイル ‘$filePath’ を作成しました。”
} else {
Write-Host “ファイル ‘$filePath’ はすでに存在します。”
}

スクリプト実行後、ファイルが存在するか確認

if (Test-Path $filePath) {
Write-Host “確認: ファイル ‘$filePath’ は存在します。”
}

後処理 (テストで作成したファイルを削除)

Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue # テスト環境で実行する場合はコメント解除

“`

この例では、(Test-Path $filePath) がファイルが存在する場合に $true、存在しない場合に $false を返します。-not (Test-Path $filePath) は、ファイルが存在しない場合に $true となり、if ブロック内の処理が実行されます。

例2: 変数が特定の値を「持たない」場合

変数 $status"Running" ではない場合に警告を表示する例です。

“`powershell

例2: 変数が特定の値を「持たない」場合

$status = “Stopped”

$status が “Running” ではないかチェック

if (-not ($status -eq “Running”)) {
Write-Host “警告: 現在のステータスは ‘Running’ ではありません ($status).”
} else {
Write-Host “ステータスは ‘Running’ です。”
}

$status = “Running”
if (-not ($status -eq “Running”)) {
Write-Host “警告: 現在のステータスは ‘Running’ ではありません ($status).”
} else {
Write-Host “ステータスは ‘Running’ です。” # こちらが実行される
}
“`

(status -eq "Running") という肯定形の条件式は、$status"Running" と等しい場合に $true を返します。-not ($status -eq "Running") は、$status"Running" と等しくない場合に $true となり、if ブロックが実行されます。

例3: コマンドレットが「結果を返さない」場合

特定の条件に一致するプロセスが存在しない場合にメッセージを表示する例です。Get-Process -Name "NonExistentProcess" のように存在しないプロセス名を指定した場合、このコマンドレットは何もオブジェクトを返さず、$null に近い状態で扱われます(厳密には空のコレクションですが、条件式での評価や $null との比較において特別な振る舞いをします。後述の $null チェックの項を参照)。PowerShellでは、空のコマンドレット出力は多くの場合、条件式で $false と評価される傾向があります(ただしこれは確実ではないため注意が必要)。より確実なのは、出力されたオブジェクトの数をチェックする方法です。

ここでは、-not を使って「特定の名前のプロセスが存在しない」という条件を表現する方法をいくつか示します。

“`powershell

例3a: 特定のプロセスが存在しない場合 (-not と Get-Process の出力を組み合わせる)

$processName = “Code” # 存在する場合は VS Code など

$processName = “DefinitelyNotExistProcess12345” # 存在しない場合

Write-Host “プロセス ‘$processName’ が実行中かチェックします…”

Get-Process はマッチするプロセスのオブジェクトを返す。存在しない場合は何も返さない。

PowerShellの挙動として、単一のオブジェクトは $true、空の出力は $false と評価されやすい傾向がある。

ただしこれは常に保証されるわけではないため、より確実な方法を推奨する(後述)。

ここでは -not の使い方の例として示す。

if (-not (Get-Process -Name $processName -ErrorAction SilentlyContinue)) {
Write-Host “情報: プロセス ‘$processName’ は実行されていません。”
} else {
Write-Host “情報: プロセス ‘$processName’ は実行中です。”
}

より確実な方法 (Countを使用)

Get-Process は常にコレクション(配列)を返す可能性があるため、Countで確認するのが最も信頼できる。

$processes = Get-Process -Name $processName -ErrorAction SilentlyContinue
if ($processes.Count -eq 0) {
Write-Host “情報 (Count確認): プロセス ‘$processName’ は実行されていません。”
} else {
Write-Host “情報 (Count確認): プロセス ‘$processName’ は実行中です。”
}

Count確認の方法を -not を使って表現することもできる

if (-not ($processes.Count -gt 0)) { # プロセスの数が0より大きくない (=0である)
Write-Host “情報 (-not Count確認): プロセス ‘$processName’ は実行されていません。”
} else {
Write-Host “情報 (-not Count確認): プロセス ‘$processName’ は実行中です。”
}
“`

例3aの最初の例のように if (-not (Get-Process ...)) は、Get-Process が何もオブジェクトを返さなかった場合に $true と評価されることを期待していますが、コマンドレットの出力が単一のオブジェクトか複数のオブジェクトかによって $true/$false への評価が微妙に異なる場合があるため、配列の.Count プロパティを使用する方がより意図が明確で堅牢です。後者の -not ($processes.Count -gt 0) は、Count が 0 より大きいという条件を否定しており、「Count が 0 である」という条件と同じ意味になります。

可読性と括弧の重要性:

-not (条件式) の形式では、条件式全体を括弧 () で囲むことが非常に重要です。これは、-not 演算子が条件式全体に適用される範囲を明確にするためです。括弧がないと、-not が条件式の一部(例えば最初の比較演算子)にのみ適用されてしまい、意図しない結果になる可能性があります。

“`powershell

括弧がない場合の注意 (多くの場合エラーになるか、意図と異なる結果になる)

以下のコードは推奨されません

if (-not $status -eq “Running”) { … } # エラーになる可能性が高い

正しい記述

if (-not ($status -eq “Running”)) { … }
“`

複数の条件を -and-or で組み合わせた式を否定する場合も、括弧を正しく使用して否定演算子の適用範囲を明確にすることが不可欠です。

“`powershell

複数の条件の否定

$a = 5
$b = 15

$a が 10 より大きく AND $b が 20 より小さい という条件の否定

つまり、$a が 10 以下 OR $b が 20 以上 の場合

if (-not (($a -gt 10) -and ($b -lt 20))) {
Write-Host “条件 (($a -gt 10) -and ($b -lt 20)) は偽です。”
} else {
Write-Host “条件 (($a -gt 10) -and ($b -lt 20)) は真です。”
}

これはド・モルガンの法則により、以下の肯定形と同じ意味になる

if (($a -le 10) -or ($b -ge 20)) {

Write-Host “条件 (($a -le 10) -or ($b -ge 20)) は真です (否定形と同じ)。”

}

“`

括弧を適切に使うことで、-not がどの部分にかかるのかが明確になり、コードの可読性が向上します。

方法2: 条件式の中で否定形の比較演算子を使用する

PowerShellには、多くの比較演算子に対応する否定形の演算子があらかじめ用意されています。これらの演算子を使うことで、条件式自体を否定の形で記述することができます。

主な否定形の比較演算子:

  • -ne (Not Equal): 〜と等しくない
  • -notlike (Not Like): ワイルドカードパターンに一致しない
  • -notmatch (Not Match): 正規表現パターンに一致しない
  • -notin (Not In): 指定したコレクションに含まれていない
  • -notcontains (Not Contains): 指定したコレクションが要素を含んでいない

これらの演算子を使用する構文は以下のようになります。

powershell
if (変数 -否定形演算子 値) {
# 条件が真の場合に実行される処理 (つまり、元の条件が偽の場合)
}

詳細な解説とサンプルコード:

この方法の利点は、条件文がより直接的に「〜ではない」という意図を表現できる点です。肯定形の条件式を考えてからそれを -not で囲むのではなく、「〜ではない」という条件を最初から否定形の演算子で記述できます。

例1: 変数が特定の値を「持たない」場合 (-ne)

これは方法1の例2と同じシナリオですが、-ne 演算子を使用します。

“`powershell

例1: 変数が特定の値を「持たない」場合 (-ne)

$status = “Stopped”

$status が “Running” と等しくないかチェック

if ($status -ne “Running”) {
Write-Host “警告: 現在のステータスは ‘Running’ ではありません ($status).”
} else {
Write-Host “ステータスは ‘Running’ です。”
}

$status = “Running”
if ($status -ne “Running”) {
Write-Host “警告: 現在のステータスは ‘Running’ ではありません ($status).”
} else {
Write-Host “ステータスは ‘Running’ です。” # こちらが実行される
}
“`

-ne-eq の否定形であり、$status -ne "Running"$status"Running" と等しくない場合に $true を返します。この記述は if (-not ($status -eq "Running")) と全く同じ意味になりますが、$status -ne "Running" の方がより簡潔で直接的です。

例2: 文字列が特定のパターンに「一致しない」場合 (-notlike, -notmatch)

ファイル名が .log で終わらない場合に処理を行う (-notlike)、あるいは特定の正規表現パターンに一致しない文字列を検出する (-notmatch) 例です。

“`powershell

例2a: 文字列が特定のワイルドカードパターンに一致しない場合 (-notlike)

$fileName1 = “application.log”
$fileName2 = “config.txt”

$pattern = “*.log” # .log で終わるファイル名

Write-Host “‘$fileName1’ が ‘$pattern’ に一致しないかチェック…”
if ($fileName1 -notlike $pattern) {
Write-Host “‘$fileName1’ は ‘$pattern’ に一致しません。”
} else {
Write-Host “‘$fileName1’ は ‘$pattern’ に一致します。” # こちらが実行される
}

Write-Host “‘$fileName2’ が ‘$pattern’ に一致しないかチェック…”
if ($fileName2 -notlike $pattern) {
Write-Host “‘$fileName2’ は ‘$pattern’ に一致しません。” # こちらが実行される
} else {
Write-Host “‘$fileName2’ は ‘$pattern’ に一致します。”
}
“`

-like はワイルドカード (*, ?) を使ったパターンマッチングを行います。-notlike はその否定です。

“`powershell

例2b: 文字列が特定の正規表現パターンに一致しない場合 (-notmatch)

$logEntry1 = “Error: File not found.”
$logEntry2 = “Info: Process started.”

$pattern = “^Error:” # “Error:” で始まる文字列

Write-Host “‘$logEntry1’ が正規表現 ‘$pattern’ に一致しないかチェック…”
if ($logEntry1 -notmatch $pattern) {
Write-Host “‘$logEntry1’ は正規表現 ‘$pattern’ に一致しません。”
} else {
Write-Host “‘$logEntry1’ は正規表現 ‘$pattern’ に一致します。” # こちらが実行される
}

Write-Host “‘$logEntry2’ が正規表現 ‘$pattern’ に一致しないかチェック…”
if ($logEntry2 -notmatch $pattern) {
Write-Host “‘$logEntry2’ は正規表現 ‘$pattern’ に一致しません。” # こちらが実行される
} else {
Write-Host “‘$logEntry2’ は正規表現 ‘$pattern’ に一致します。”
}
“`

-match は正規表現を使ったパターンマッチングを行います。-notmatch はその否定です。-match はマッチした場合に $true を返すだけでなく、マッチした部分文字列などを自動変数 $Matches に格納する副作用がありますが、-notmatch にはそのような副作用はありません。

例3: コレクションに特定の要素が含まれていない場合 (-notin, -notcontains)

特定のユーザーが管理者グループに「含まれていない」か確認する (-notin)、あるいは特定のサーバーリストに指定のサーバー名が「含まれていない」か確認する (-notcontains) 例です。

-in-notin は、左辺の要素が右辺のコレクションに「含まれているか/含まれていないか」をチェックします。
-contains-notcontains は、左辺のコレクションが右辺の要素を「含んでいるか/含んでいないか」をチェックします。

“`powershell

例3a: コレクションに特定の要素が含まれていない場合 (-notin)

$allowedUsers = @(“Alice”, “Bob”, “Charlie”)
$currentUser = “David”

$currentUser = “Alice”

Write-Host “$currentUser が許可されたユーザーリストに含まれていないかチェック…”
if ($currentUser -notin $allowedUsers) {
Write-Host “ユーザー ‘$currentUser’ は許可されたユーザーリストに含まれていません。” # $currentUser が David の場合に実行
} else {
Write-Host “ユーザー ‘$currentUser’ は許可されたユーザーリストに含まれています。” # $currentUser が Alice の場合に実行
}
“`

“`powershell

例3b: コレクションが特定の要素を含んでいない場合 (-notcontains)

$serverList = @(“Server01”, “Server02”, “Server03”)
$targetServer = “Server04”

$targetServer = “Server01”

Write-Host “サーバーリストが ‘$targetServer’ を含んでいないかチェック…”
if ($serverList -notcontains $targetServer) {
Write-Host “サーバーリストは ‘$targetServer’ を含んでいません。” # $targetServer が Server04 の場合に実行
} else {
Write-Host “サーバーリストは ‘$targetServer’ を含んでいます。” # $targetServer が Server01 の場合に実行
}
“`

-notin-notcontains は、それぞれ -in-contains の否定形です。どちらを使うかは、要素をリストに対してチェックするのか ( -in/-notin )、リストが要素を含んでいるかをチェックするのか ( -contains/-notcontains ) という表現のニュアンスで選び分けられます。多くの場合、リストが大きい場合は -contains/-notcontains の方が効率が良いとされています。

その他の否定形演算子:

数値や日付などの比較演算子 (-gt, -lt, -ge, -le) にも否定形は存在しますが、あまり一般的ではありません。例えば、-notgt (Not Greater Than) は -le (Less than or Equal) と同じ意味になります。

  • -notgt (Not Greater Than) は -le と同じ
  • -notge (Not Greater than or Equal) は -lt と同じ
  • -notlt (Not Less Than) は -ge と同じ
  • -notle (Not Less than or Equal) は -gt と同じ

これらの否定形演算子を使うよりは、対応する肯定形の <=>= などを使う方が、広く理解されているため推奨されます。

“`powershell

例: -notgt と -le の比較 (推奨は -le)

$value = 10

if ($value -notgt 5) { Write-Host “$value は 5 より大きくない (つまり 5 以下)です。” } # あまり見慣れない

if ($value -le 5) { Write-Host “$value は 5 以下です。” } # こちらが一般的
“`

方法1と方法2の比較:

  • 方法1 (-not (条件式)): 汎用的で、あらゆる条件式に適用できます。元の肯定形の条件式が明確な場合に、それを否定するだけで済みます。複雑な条件式全体を否定する場合に適しています。
  • 方法2 (変数 -否定形演算子 値): 条件式が単一の比較である場合に、より簡潔で意図が直接的に伝わる記述になります。特に -ne, -notlike, -notmatch, -notin, -notcontains は頻繁に使用されます。

どちらの方法を選択するかは、状況や個人のコーディングスタイル、チームのコーディング規約によります。単一の簡単な比較を否定する場合は方法2、複数の条件を組み合わせた複雑な式全体を否定する場合は方法1が適していることが多いでしょう。

方法3: コマンドレットの出力や変数の暗黙的な真偽値評価を利用・否定する

PowerShellでは、真偽値だけでなく、他の型の値も条件式の中で評価される際に暗黙的に真偽値に変換されることを前述しました。特に重要なのは、$null、空文字列 ("")、数値の 0$false と評価されるという特性です。

この特性を利用して、「値が存在しない」「文字列が空である」「数値がゼロである」といった条件をチェックできます。そして、これらの条件の否定、つまり「値が存在する」「文字列が空ではない」「数値がゼロではない」といった条件を if 文で表現することができます。

構文は以下のようになります。

“`powershell

値が $false と評価されるかどうかをチェック

if (条件式) {
# 条件式が $true と評価される場合に実行 (つまり、値が存在する、文字列が空でない、など)
}

値が $false と評価されないかどうかをチェック (-not を使用)

if (-not 条件式) {
# 条件式が $false と評価される場合に実行 (つまり、値が存在しない、文字列が空、など)
}
“`

詳細な解説とサンプルコード:

この方法は、特に変数やコマンドレットの出力が $null かどうか、または空であるかどうかをチェックする際によく使用されます。

例1: 変数が $null または空文字列ではないかチェック

PowerShellでは、$null や空文字列は条件式で $false と評価されます。したがって、これらの値ではない(つまり、何らかの値が入っている)という条件は、変数名をそのまま if の条件式に使用することで表現できます。

“`powershell

例1a: 変数が $null または空文字列ではないかチェック (肯定的表現)

$variable1 = “Some Value”
$variable2 = “”
$variable3 = $null

Write-Host “変数 variable1 に値があるかチェック…”
if ($variable1) { # $variable1 は空文字列でも $null でもない -> $true
Write-Host “variable1 には値があります: ‘$variable1′”
} else {
Write-Host “variable1 は $null または空文字列です。”
}

Write-Host “変数 variable2 に値があるかチェック…”
if ($variable2) { # $variable2 は空文字列 -> $false
Write-Host “variable2 には値があります: ‘$variable2′”
} else {
Write-Host “variable2 は $null または空文字列です。” # こちらが実行される
}

Write-Host “変数 variable3 に値があるかチェック…”
if ($variable3) { # $variable3 は $null -> $false
Write-Host “variable3 には値があります: ‘$variable3′”
} else {
Write-Host “variable3 は $null または空文字列です。” # こちらが実行される
}
“`

この $variable を条件式に直接使用する方法は、「$variable$null や空文字列などの ‘空’ や ‘ゼロ’ に相当する値ではない」という条件を簡潔に表現できます。

例1b: 変数が $null または空文字列であるかチェック (否定的表現: if not $variable)

上記の否定、つまり「変数に値がない」($null または空文字列である)という条件は、-not 演算子を使って変数名を否定することで表現できます。

“`powershell

例1b: 変数が $null または空文字列であるかチェック (否定的表現: if (-not $variable))

$variable1 = “Some Value”
$variable2 = “”
$variable3 = $null

Write-Host “変数 variable1 に値がないかチェック…”
if (-not $variable1) { # $variable1 は $true 評価 -> -not ($true) は $false
Write-Host “variable1 は $null または空文字列です。”
} else {
Write-Host “variable1 には値があります: ‘$variable1′” # こちらが実行される
}

Write-Host “変数 variable2 に値がないかチェック…”
if (-not $variable2) { # $variable2 は $false 評価 -> -not ($false) は $true
Write-Host “variable2 は $null または空文字列です。” # こちらが実行される
} else {
Write-Host “variable2 には値があります: ‘$variable2′”
}

Write-Host “変数 variable3 に値がないかチェック…”
if (-not $variable3) { # $variable3 は $null -> $false 評価 -> -not ($false) は $true
Write-Host “variable3 は $null または空文字列です。” # こちらが実行される
} else {
Write-Host “variable3 には値があります: ‘$variable3′”
}
“`

if (-not $variable) は、「$variable$false と評価される値である」という条件を簡潔に表現する方法です。これは $null, "", 0 などに対して $true となります。

$null チェックにおける注意点とベストプラクティス:

if ($variable -eq $null) または if ($variable -ne $null) という明示的な $null チェックもよく行われます。しかし、特に $variable がまだ一度も定義されていない可能性がある場合や、コマンドレットの出力が全くなかった場合に、$variable 自体を評価しようとするとエラーになることがあります。

この問題を回避するための推奨されるプラクティスは、比較演算子の左辺に $null を置くことです。if ($null -eq $variable) または if ($null -ne $variable) のように記述します。こうすることで、たとえ $variable が存在しなくてもエラーにならず、意図通りに評価が実行されます。

“`powershell

$null チェックのベストプラクティス

変数 $undefinedVariable はまだ定義されていないとする

以下はエラーになる可能性がある (PowerShellのバージョンや環境による)

if ($undefinedVariable -eq $null) { Write-Host ‘$undefinedVariable は $null です。’ }

if ($undefinedVariable -ne $null) { Write-Host ‘$undefinedVariable は $null ではありません。’ }

以下は安全

if ($null -eq $undefinedVariable) { Write-Host ‘$undefinedVariable は $null です (安全なチェック)。’ } # こちらが $true になる
if ($null -ne $undefinedVariable) { Write-Host ‘$undefinedVariable は $null ではありません (安全なチェック)。’ }
“`

したがって、「変数に $null または空文字列/ゼロ以外の値があるか」というチェックには if ($variable) が便利ですが、「変数に $null が入っているか」というチェックには $null -eq $variable という形式が最も安全で推奨されます。

これらを踏まえて、「変数に $null または空文字列やゼロが入っているか」という否定的な条件 (if not $variable) を書く場合は、if (-not $variable) が簡潔ですが、$null のチェックをより厳密に行いたい場合は if (($null -eq $variable) -or ($variable -eq "") -or ($variable -eq 0)) のように詳細に記述する必要が出てくる場合もあります。しかし、多くのシナリオでは if (-not $variable) の簡潔さで十分です。

例2: コマンドレットが結果を「返さない」場合 ($null と空コレクションの挙動)

Get-Process -Name "NonExistentProcess" のように、存在しないオブジェクトを取得しようとするコマンドレットは、多くの場合 $null を返すか、要素数ゼロのコレクション(配列)を返します。

前述のように $null$false と評価されますが、要素数ゼロのコレクションは PowerShell のバージョンによっては $false とは評価されません。そのため、コマンドレットが結果を返さなかったことを検出するには、出力されたオブジェクトの数 (.Count) を確認するのが最も確実です。

“`powershell

例2: コマンドレットが結果を「返さない」場合 (確実な方法)

$processName = “DefinitelyNotExistProcessXYZ”
$process = Get-Process -Name $processName -ErrorAction SilentlyContinue

$process が $null または空のコレクションであるかをチェック

Get-Process は通常、マッチしない場合は何も返さないか、要素数0の配列を返す。

要素数0の配列は $false と評価されないことがあるため、Count をチェックするのが確実。

if ($process.Count -eq 0) {
Write-Host “情報: プロセス ‘$processName’ は実行されていません (Countチェック)。”
} else {
Write-Host “情報: プロセス ‘$processName’ は実行中です (Countチェック)。”
}

あるいは、Count が 0 より大きくない (-not と Count を組み合わせる)

if (-not ($process.Count -gt 0)) {
Write-Host “情報: プロセス ‘$processName’ は実行されていません (-not Countチェック)。”
} else {
Write-Host “情報: プロセス ‘$processName’ は実行中です (-not Countチェック)。”
}

参考:もしコマンドレットが確実に $null を返すことが分かっている場合(稀だが)

if ($null -eq $process) { Write-Host “プロセス ‘$processName’ は $null です。” }

“`

したがって、「コマンドレットが何も結果を返さなかった場合」という否定的な条件をチェックするには、出力されたオブジェクトのコレクションの .Count プロパティが 0 であるか、あるいは Count -gt 0 という条件を -not で否定するのが最も推奨される方法です。if (-not $result) のように結果を直接否定する方法は、結果が単一のオブジェクトや $null の場合は期待通りに動作しやすいですが、空のコレクションの場合は意図通りにならない可能性があるため、避けるのが無難です。

具体的なユースケースとサンプルコード(まとめ)

これまでに解説した様々な「否定」の表現方法を、具体的なユースケースの中でどのように使い分けるかを見ていきましょう。

ユースケース1: ファイルまたはディレクトリが存在しない場合に処理を行う

最も一般的なシナリオの一つです。Test-Path を使用します。

  • 方法1 (-not (Test-Path ...)): 最も一般的で推奨される方法です。
    powershell
    $path = "C:\Temp\MyAppLog.txt"
    if (-not (Test-Path $path)) {
    Write-Host "'$path' が存在しません。作成します..."
    New-Item -Path $path -ItemType File | Out-Null
    }
  • 方法2 ((Test-Path ...) -eq $false): 意味は同じですが、冗長に感じられます。しかし、$false と明示的に比較することで、真偽値をチェックしていることがより明確になるという利点もあります。
    powershell
    $path = "C:\Temp\MyAppLog.txt"
    if ((Test-Path $path) -eq $false) {
    Write-Host "'$path' が存在しません。作成します (明示的比較)..."
    New-Item -Path $path -ItemType File | Out-Null
    }

    この形式は、-not を使うことに慣れていない人にとっては理解しやすいかもしれません。

ユースケース2: 特定のサービスが実行されていない場合に開始する

Get-Service コマンドレットの Status プロパティを使用します。

“`powershell
$serviceName = “Spooler” # 印刷スプーラー サービス
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue

サービスが存在するかどうかのチェックも重要

if ($null -eq $service) {
Write-Host “サービス ‘$serviceName’ は存在しません。”
} else {
# サービスが存在する場合、そのステータスをチェック
Write-Host “サービス ‘$serviceName’ の現在のステータス: $($service.Status)”

# ステータスが "Running" ではないかチェック
# 方法2の -ne 演算子が最も自然です。
if ($service.Status -ne "Running") {
    Write-Host "'$serviceName' が実行されていません。開始します..."
    Start-Service -Name $serviceName -ErrorAction SilentlyContinue
    # サービスが開始されたか再確認するなどの処理を追加
    Start-Sleep -Seconds 2 # 少し待つ
    $service = Get-Service -Name $serviceName # ステータス更新
    Write-Host "'$serviceName' の新しいステータス: $($service.Status)"
} else {
    Write-Host "'$serviceName' はすでに実行中です。"
}

}
``
この例では、
$service.Status -ne “Running”という否定形の比較演算子を使用する方法が最も直接的で読みやすいです。if (-not ($service.Status -eq “Running”))と書いても同じ意味ですが、-ne` の方が一般的です。

ユースケース3: 配列に特定の要素が含まれていない場合に要素を追加する

@() で定義された配列に要素を追加する前に、すでに含まれていないか確認します。

“`powershell
$myArray = @(“Apple”, “Banana”, “Cherry”)
$newItem = “Date”

$newItem = “Banana” # すでに含まれている場合

Write-Host “配列に ‘$newItem’ が含まれていないかチェック…”

方法2の -notin 演算子が最も適しています。

if ($newItem -notin $myArray) {
Write-Host “‘$newItem’ は配列に含まれていません。追加します。”
$myArray += $newItem # 要素を追加
Write-Host “新しい配列: $($myArray -join ‘, ‘)”
} else {
Write-Host “‘$newItem’ はすでに配列に含まれています。”
}

$newItem = “Banana”
if ($newItem -notin $myArray) {
Write-Host “‘$newItem’ は配列に含まれていません。追加します。”
$myArray += $newItem
Write-Host “新しい配列: $($myArray -join ‘, ‘)”
} else {
Write-Host “‘$newItem’ はすでに配列に含まれています。” # こちらが実行される
}
``-notin演算子は、この「コレクションに要素が含まれていないか」という条件を非常に簡潔に表現できます。if (-not ($myArray -contains $newItem))と書いても同じ意味ですが、-notin` の方がより直接的です。

ユースケース4: 変数が $null または空文字列でない場合に処理を行う

変数に有効な値が設定されていることを確認してから処理に進むシナリオです。

“`powershell

変数に値があるかチェック

$configValue1 = “Enabled”
$configValue2 = “”
$configValue3 = $null

方法3の肯定的表現 (if ($variable)) が最も簡潔です。

Write-Host “configValue1 に値があるかチェック…”
if ($configValue1) { # “Enabled” は $true と評価される
Write-Host “configValue1 は有効な値です: ‘$configValue1′”
# 値を使った処理…
} else {
Write-Host “configValue1 は $null または空です。”
}

Write-Host “configValue2 に値があるかチェック…”
if ($configValue2) { # “” は $false と評価される
Write-Host “configValue2 は有効な値です: ‘$configValue2′”
} else {
Write-Host “configValue2 は $null または空です。” # こちらが実行される
}

Write-Host “configValue3 に値があるかチェック…”
if ($configValue3) { # $null は $false と評価される
Write-Host “configValue3 は有効な値です: ‘$configValue3′”
} else {
Write-Host “configValue3 は $null または空です。” # こちらが実行される
}

変数が $null または空文字列であるかチェックしたい場合

方法3の否定的表現 (if (-not $variable)) が簡潔です。

Write-Host “configValue1 が $null または空かチェック…”
if (-not $configValue1) { # “Enabled” -> $true -> -not $true -> $false
Write-Host “configValue1 は $null または空です。”
} else {
Write-Host “configValue1 は有効な値です: ‘$configValue1′” # こちらが実行される
}
``
変数に値があること (
if ($variable)) または値がないこと (if (-not $variable)) をチェックするこの方法は、非常に一般的で簡潔ですが、数値の0$falseと評価されることに注意が必要です。もし数値の0を有効な値として扱いたい場合は、明示的に$variable -eq $null$variable -eq “”` などをチェックする必要があります。

可読性とベストプラクティス

ここまでで、PowerShellで条件を否定する様々な方法があることがわかりました。どの方法を選ぶべきでしょうか? 重要なのは、スクリプトの可読性意図の明確さです。

  1. 簡潔さと直接性:

    • 単一の簡単な比較を否定する場合は、-ne, -notlike, -notmatch, -notin, -notcontains のような否定形演算子を使用するのが最も簡潔で直接的です。例: if ($status -ne "Running"), if ($fileName -notlike "*.log").
    • 変数やコマンドレットの出力が $null や空であるかどうかのチェックには、if (-not $variable) または if ($variable.Count -eq 0) が簡潔です。ただし $null チェックは $null -eq $variable が安全な形式です。
  2. 汎用性と複雑な条件:

    • 複数の条件を -and-or で組み合わせた複雑な条件式全体を否定する場合は、-not (条件式) の形式が最も汎用的で適しています。例: if (-not (($a -gt 10) -and ($b -lt 20))).
  3. 括弧の使用:

    • -not 演算子を使用する場合は、必ず条件式の全体を括弧 () で囲み、-not の適用範囲を明確にしてください。if (-not (条件式)) の形を常に意識しましょう。
  4. 肯定形と否定形:

    • 可能であれば、肯定形で条件を書いた方が直感的に理解しやすい場合があります。例えば、「ファイルが存在しない場合」を if (-not (Test-Path $path)) と書く代わりに、ファイルの存在をチェックして、存在しないという結果に基づいて処理を分ける、という考え方もできます。しかし、多くの場合、「〜ではない場合」という意図は明確であり、否定形の表現を使うことが自然です。
    • 重要なのは、書いているコードが「〜である場合」の処理なのか「〜ではない場合」の処理なのかを、自分だけでなく他の人が読んだときにもすぐに理解できることです。否定形を使う場合は、その条件が何を否定しているのかが明確になるように記述しましょう。
  5. コメント:

    • 特に複雑な条件や、-not と複数の論理演算子を組み合わせる場合は、コメントでその条件が何を意図しているのかを補足すると、さらに可読性が向上します。

よくある落とし穴

  • $null と空コレクションの扱い: 前述のように、$null$false と評価されますが、要素数ゼロのコレクションは $false とは評価されない場合があります。コマンドレットの出力がコレクションになる可能性がある場合は、.Count -eq 0 で空かどうかをチェックするのが最も安全です。また、$null との比較は $null -eq $variable の形式を推奨します。
  • 演算子の優先順位と括弧: -not-and, -or などの論理演算子、そして比較演算子には優先順位があります。意図しない評価順序を防ぐために、迷ったら積極的に括弧を使用しましょう。特に -not を条件式全体に適用する場合は、if (-not (条件式)) という括弧を忘れないでください。
  • 文字列比較での大文字・小文字: PowerShellのデフォルトの文字列比較 (-eq, -ne, -like, -notlike, -match, -notmatch) は、大文字・小文字を区別しません。大文字・小文字を区別したい場合は、-ceq, -cne, -clike, -cnotlike, -cmatch, -cnotmatch のように -c を接頭辞として付けた演算子を使用してください。

“`powershell

大文字・小文字を区別する比較の例

$name = “Alice”

デフォルト (区別しない)

if ($name -eq “alice”) { Write-Host “‘Alice’ はデフォルト比較で ‘alice’ と等しい。” } # True

大文字・小文字を区別する

if ($name -ceq “alice”) { Write-Host “‘Alice’ は -ceq 比較で ‘alice’ と等しい。” } # False
if ($name -cne “alice”) { Write-Host “‘Alice’ は -cne 比較で ‘alice’ と等しくない。” } # True (否定形)
“`

まとめ

PowerShellにおけるif not、つまり条件の否定を表現する方法は複数あります。

  1. -not (条件式): 最も汎用的で、あらゆる条件式全体を否定する際に使用できます。複雑な条件式に特に有効です。可読性を高めるためには括弧の使用が不可欠です。
  2. 否定形演算子 (-ne, -notlike, -notmatch, -notin, -notcontains など): 単一の比較を否定する際に、より簡潔で直接的な表現を提供します。よく使われるシナリオに特化しており、可読性が高いです。
  3. -not 変数-not コマンドレット出力: 変数やコマンドレットの出力が $null や空文字列 (""), 数値 0 など、PowerShellで $false と評価される値であるかどうかをチェックする際に使用できます。非常に簡潔ですが、空のコレクションの扱いに注意が必要です。$null チェックには $null -eq $variable の形式が安全です。

これらの方法の中から、表現したい条件に最も合致し、かつスクリプトの読者(将来の自分自身や他の開発者)にとって最も理解しやすい方法を選択することが重要です。

適切な方法で「〜ではない場合」の条件分岐を使いこなすことは、より堅牢で読みやすいPowerShellスクリプトを作成するための重要なスキルです。本記事で解説した内容とサンプルコードを参考に、あなたのスクリプト作成に役立ててください。PowerShellの柔軟な表現力を活かして、効果的なスクリプトを記述していきましょう。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール