Skip to content

PowerShell Conditional Branching

How to use PowerShell's if, elseif, else, and switch statements for structured conditional logic, including comparison operators, wildcards, regex, and PowerShell 7's ternary operator.

Conditional branching controls the flow of script execution by evaluating logical expressions and running specific code blocks based on whether conditions evaluate to $true or $false. PowerShell provides structured conditional statements, including if, elseif, else, and switch. These replace unstructured jump mechanisms (like Batch's goto) with readable, maintainable control flow. PowerShell 7 also adds a compact ternary operator for simple inline assignments.

The if Statement

The if statement evaluates a conditional test. If the condition is true, the script block within the curly braces ({}) executes.

if-statement.ps1powershell
$temperature = 85

if ($temperature -gt 80) {
    Write-Output "It's hot outside."
}

where:

  • The condition $temperature -gt 80 is enclosed in parentheses.
  • -gt is the greater than comparison operator.
  • The code block in { } runs only if the condition is $true.
Consolepowershell
./if-statement.ps1
Outputplaintext
It's hot outside.

if / elseif / else

Chain additional conditions using elseif, and provide a fallback with else.

Basic Syntax

if (<condition1>) {
}
elseif (<condition2>) {
}
else {
}

Condition Evaluation

Unlike languages that rely on comparison symbols (==, >, <), PowerShell uses hyphenated comparison operators such as -gt, -ge, -lt, -le, -eq, -ne.

if-elseif-else.ps1powershell
$score = 72

if ($score -ge 90) {
    Write-Output "Grade: A"
} elseif ($score -ge 80) {
    Write-Output "Grade: B"
} elseif ($score -ge 70) {
    Write-Output "Grade: C"
} else {
    Write-Output "Grade: F"
}
Consolepowershell
./if-elseif-else.ps1
Outputplaintext
Grade: C

where:

  • Conditions are evaluated top to bottom; the first one that evaluates to $true runs, and the rest are skipped.
  • else catches any case not matched by the preceding conditions.

A CPU-utilization example:

evaluate-numbers.ps1powershell
$CpuLoad = 85

if ($CpuLoad -ge 90) {
    Write-Warning "Critical CPU utilization: $CpuLoad%"
}
elseif ($CpuLoad -ge 75) {
    Write-Warning "Elevated CPU utilization: $CpuLoad%"
}
else {
    Write-Output "CPU utilization normal: $CpuLoad%"
}
Consolepowershell
pwsh ./evaluate-numbers.ps1
Outputplaintext
WARNING: Elevated CPU utilization: 85%

Nested if Statements

An if statement can be placed inside another if block to test additional conditions only when the outer condition is met.

nested-if.ps1powershell
$isLoggedIn = $true
$role = "Admin"

if ($isLoggedIn) {
    if ($role -eq "Admin") {
        Write-Output "Access granted: full admin dashboard."
    } else {
        Write-Output "Access granted: standard user dashboard."
    }
} else {
    Write-Output "Access denied: please log in."
}
Outputplaintext
Access granted: full admin dashboard.

Evaluating Variables and System State

PowerShell streamlines conditional checks that required specialized keywords in legacy shells like Batch (IF DEFINED, IF EXIST, IF ERRORLEVEL).

Checking for $null or Empty

Example of $null Checkpowershell
$value = $null

if ($null -eq $value) {
    Write-Output "Value is null."
}
Outputplaintext
Value is null.

Checking Integer Variables

Example of Integer Checkpowershell
$count = 0

if ($count -eq 0) {
    Write-Output "Count is zero."
}
Outputplaintext
Count is zero.

Checking String Variables

Example of String Checkpowershell
$username = ""

if ([string]::IsNullOrEmpty($username)) {
    Write-Output "Username is empty."
}
Outputplaintext
Username is empty.

where [string]::IsNullOrEmpty() is a static .NET method that safely checks for both $null and an empty string ("") in a single call.

Variable Verification vs. Batch IF DEFINED

To check whether a variable is assigned and contains data, compare it against $null:

Consolepowershell
if ($null -ne $DeploymentPath) {
    Write-Output "Target path set: $DeploymentPath"
} else {
    Write-Output "DeploymentPath variable is unassigned."
}

To test whether a variable identifier exists in memory at all (even if assigned $null), query the variable provider:

Consolepowershell
if (Test-Path -Path "Variable:DeploymentPath") {
    Write-Output "Variable exists in current scope."
}

Checking Command-Line Arguments

check-args.ps1powershell
param(
    [string]$Name
)

if ([string]::IsNullOrEmpty($Name)) {
    Write-Output "No name provided."
} else {
    Write-Output "Hello, $Name!"
}
Consolepowershell
./check-args.ps1 -Name "Tom"
Outputplaintext
Hello, Tom!

Filesystem Verification vs. Batch IF EXIST

File and directory validation is handled directly by the Test-Path cmdlet:

Example of Test-Pathpowershell
if (Test-Path -Path "C:\Configs\settings.json" -PathType Leaf) {
    Write-Output "Configuration file found."
} else {
    Write-Error "Required settings file is missing."
}

where -PathType Leaf ensures the target is a file rather than a directory container.

A simpler example:

Consolepowershell
if (Test-Path "C:\Logs\app.log") {
    Write-Output "Log file exists."
} else {
    Write-Output "Log file not found."
}
Outputplaintext
Log file exists.

Execution Results vs. Batch IF ERRORLEVEL

To check whether a previous command executed successfully or failed:

  • $?: Contains $true if the immediately preceding PowerShell command succeeded; $false if it generated an error.
  • $LASTEXITCODE: Stores the integer exit code of the last native external CLI executable run (0 normally indicates success; non-zero indicates an error).
Consolepowershell
git status 2>$null
if ($LASTEXITCODE -ne 0) {
    Write-Warning "Directory is not a tracked Git repository."
}

The Absence of goto

Legacy batch files rely heavily on :label and goto label jumps to create loops and conditionals. PowerShell does not have a goto statement. Instead, control flow is structured using functions, conditional blocks (if/else), and loop constructs (foreach, while, break, continue).

Batch-to-PowerShell Equivalents Table

Batch Concept PowerShell Equivalent
if defined VAR if (Test-Path variable:VAR) or if ($null -ne $VAR)
if exist file.txt if (Test-Path "file.txt")
if errorlevel 1 if ($LASTEXITCODE -ne 0) or checking $?
goto :label Not used in PowerShell. Use functions, loops, or switch instead

The switch Statement

The switch statement evaluates an expression against multiple matching criteria. It is simpler and more readable than writing repetitive if-elseif-else chains.

Basic Syntax

switch-basic.ps1powershell
$day = "Wed"

switch ($day) {
    "Mon" { Write-Output "Start of the week" }
    "Wed" { Write-Output "Midweek" }
    "Fri" { Write-Output "Almost weekend" }
    default { Write-Output "Just another day" }
}

where:

  • Each label ("Mon", "Wed", etc.) is compared against $day in order.
  • default runs only if none of the preceding labels match, equivalent to else.
Consolepowershell
./switch-basic.ps1
Outputplaintext
Midweek

A second example using explicit break statements:

switch-basic-explicit-break.ps1powershell
$Environment = "Staging"

switch ($Environment) {
    "Development" { Write-Output "Deploying to DEV cluster."; break }
    "Staging"     { Write-Output "Deploying to STAGING cluster."; break }
    "Production"  { Write-Output "Deploying to PROD cluster."; break }
    Default       { Write-Output "Unknown environment specified."; break }
}

where:

  • Default executes if none of the explicit conditions match.
  • break stops further condition evaluation.

switch with Wildcards and Regex

The switch statement supports pattern matching modes using the -Wildcard and -Regex parameters, as well as direct file reading with -File.

Wildcard Matching (-Wildcard)

The -Wildcard parameter allows matching strings using standard shell wildcards (*, ?):

switch-wildcard.ps1powershell
$file = "report_2026.csv"

switch -Wildcard ($file) {
    "*.csv" { Write-Output "CSV file detected." }
    "*.txt" { Write-Output "Text file detected." }
    default { Write-Output "Unknown file type." }
}
Outputplaintext
CSV file detected.

A second example demonstrating default fallthrough (no break):

switch-wildcard-multi.ps1powershell
$FileName = "report-2026-q3.csv"

switch -Wildcard ($FileName) {
    "*.log"     { Write-Output "Target is a system log file." }
    "report-*"  { Write-Output "Target is an analytical report." }
    "*.csv"     { Write-Output "Target is a CSV spreadsheet." }
}
Outputplaintext
Target is an analytical report.
Target is a CSV spreadsheet.

Note that both blocks executed because no break statement was used.

Regex Matching (-Regex)

The -Regex parameter evaluates patterns using regular expressions and automatically populates the $Matches automatic variable for each matching clause.

switch-regex.ps1powershell
$input = "Error Code: 404"

switch -Regex ($input) {
    "\d{3}" { Write-Output "Contains a 3-digit code." }
    "Error" { Write-Output "This is an error message." }
}

where:

  • -Regex enables full regular expression pattern matching for each case label.
  • Because switch evaluates every case by default, both cases above match and both output lines execute.
Outputplaintext
Contains a 3-digit code.
This is an error message.

A more advanced example using named capture groups:

switch-regex-named.ps1powershell
$ServerIdentifier = "LON-DB-PROD-01"

switch -Regex ($ServerIdentifier) {
    "^(?<Region>[A-Z]{3})-(?<Role>[A-Z]+)-(?<Env>[A-Z]+)-\d+$" {
        [PSCustomObject]@{
            Region = $Matches.Region
            Role   = $Matches.Role
            Env    = $Matches.Env
        }
        break
    }
    Default {
        Write-Warning "Server string does not match standard corporate naming pattern."
    }
}
Outputplaintext
Region Role Env
------ ---- ---
LON    DB   PROD

Reading Files Directly (-File)

Using the -File parameter, switch reads a file line by line without needing Get-Content, testing each line against the conditions:

switch -Regex -File "C:\Logs\app.log" {
    "FATAL" { Write-Error "Fatal line detected: $_" }
    "WARN"  { Write-Warning "Warning line detected: $_" }
}

The Ternary Operator (PowerShell 7+)

PowerShell 7 introduced the ternary operator (?:) as a compact shorthand for simple if/else assignments.

Syntax:

<condition> ? <if-true> : <if-false>
Example of Ternary Operatorpowershell
$age = 20
$status = $age -ge 18 ? "Adult" : "Minor"
Write-Output $status
Outputplaintext
Adult
Example of Ternary with Booleanpowershell
$ServiceRunning = $true
$HostStatus = $ServiceRunning ? "Online" : "Offline"
$HostStatus
Outputplaintext
Online

where:

  • The condition ($age -ge 18 or $ServiceRunning) is evaluated first.
  • If $true, the value before : is returned; if $false, the value after : is returned.

In Windows PowerShell 5.1, you can achieve the same inline assignment using subexpression conditionals:

Consolepowershell
$HostStatus = if ($ServiceRunning) { "Online" } else { "Offline" }

Practical Example: Deployment Target Validator

The following script accepts target parameters, evaluates disk capacity, verifies local prerequisites using Test-Path, and routes deployment actions using switch:

validate-deployment-node.ps1powershell
param (
    [string]$NodeRole = "Web",
    [string]$ConfigPath = "C:\App\appsettings.json"
)

if (-not (Test-Path -Path $ConfigPath)) {
    Write-Warning "Configuration not found at $ConfigPath. Creating default baseline."
    $ConfigValid = $false
} else {
    $ConfigValid = $true
}

$DeploymentAction = switch ($NodeRole) {
    "Web"     { "Deploying ASP.NET Core Runtime and Kestrel Bindings" }
    "DB"      { "Initializing SQL Server instances and storage mounts" }
    "Cache"   { "Configuring Redis memory limits" }
    Default   { "Unsupported role: '$NodeRole'. Terminating." }
}

[PSCustomObject]@{
    RoleTested      = $NodeRole
    ConfigPresent   = $ConfigValid
    ActionPlan      = $DeploymentAction
    EvaluatedByUser = $env:USERNAME
    Timestamp       = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
}

where:

  • Test-Path checks whether the specified config file exists.
  • The switch statement assigns a deployment strategy directly to $DeploymentAction.
  • [PSCustomObject] aggregates the resulting configuration into a structured record.

Execute the script from the console:

Consolepowershell
pwsh ./validate-deployment-node.ps1 -NodeRole "Web" -ConfigPath "C:\Missing\appsettings.json"
Outputplaintext
WARNING: Configuration not found at C:\Missing\appsettings.json. Creating default baseline.

RoleTested      : Web
ConfigPresent   : False
ActionPlan      : Deploying ASP.NET Core Runtime and Kestrel Bindings
EvaluatedByUser : Tom
Timestamp       : 2026-09-22 08:40:24
Navigation