Lesson 5 of 5  ·  Beginner

Control Flow: If, Loops & Functions

⏱ ~25 minutes Beginner

If / ElseIf / Else

Make decisions in your scripts with if, elseif, and else. The condition goes in ( ) and the code to run goes in { }.

If / ElseIf / Else
$temperature = 22

if ($temperature -gt 30) {
    Write-Host "It's hot outside!"
} elseif ($temperature -gt 15) {
    Write-Host "Nice weather."
} elseif ($temperature -gt 0) {
    Write-Host "A bit chilly."
} else {
    Write-Host "Freezing!"
}
Nice weather.
Practical If Examples
# Check if a file exists before using it
if (Test-Path "C:\data\report.csv") {
    $data = Import-Csv "C:\data\report.csv"
    Write-Host "Loaded $($data.Count) records."
} else {
    Write-Host "Report file not found!" -ForegroundColor Red
}

# Negate with -not or !
if (-not (Test-Path "C:\Output")) {
    New-Item -ItemType Directory -Path "C:\Output"
    Write-Host "Created output directory."
}

Switch — Multiple Conditions

switch is cleaner than a long chain of elseif blocks when you're comparing one value against many possibilities:

Switch Statement
$day = "Monday"

switch ($day) {
    "Monday" { Write-Host "Start of the work week." }
    "Friday" { Write-Host "Almost the weekend!" }
    "Saturday" { Write-Host "Weekend!" }
    "Sunday" { Write-Host "Weekend!" }
    default { Write-Host "A regular weekday." }
}
Start of the work week.

# Switch supports wildcards with -Wildcard
switch -Wildcard ($filename) {
    "*.log" { Write-Host "Log file" }
    "*.csv" { Write-Host "CSV file" }
    "*.txt" { Write-Host "Text file" }
    default { Write-Host "Unknown type" }
}

For Loop

A for loop repeats code a specific number of times with a counter variable:

For Loop
# Count from 1 to 5
for ($i = 1; $i -le 5; $i++) {
    Write-Host "Count: $i"
}
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

# Or use the simpler range syntax with foreach
foreach ($num in 1..5) {
    Write-Host $num
}

ForEach Loop

The foreach loop (not to be confused with ForEach-Object in pipelines) iterates over a collection. It's often cleaner than a for loop when you have an array:

ForEach Loop
$servers = "web01", "web02", "db01", "db02"

foreach ($server in $servers) {
    if (Test-Connection $server -Count 1 -Quiet) {
        Write-Host "$server is online" -ForegroundColor Green
    } else {
        Write-Host "$server is OFFLINE!" -ForegroundColor Red
    }
}

While and Do-While Loops

While / Do-While
# While — checks condition BEFORE each run
$count = 0
while ($count -lt 5) {
    Write-Host "count = $count"
    $count++
}

# Do-While — runs at LEAST once, checks after
do {
    $input = Read-Host "Enter 'quit' to stop"
} while ($input -ne "quit")

# break exits a loop early
foreach ($i in 1..100) {
    if ($i -eq 5) { break } # stops at 5
    Write-Host $i
}

# continue skips the rest of this iteration
foreach ($i in 1..10) {
    if ($i % 2 -eq 0) { continue } # skip evens
    Write-Host $i # prints 1, 3, 5, 7, 9
}

Functions

Functions let you package reusable code with a name. Define it once, call it many times. Functions in PowerShell use the function keyword:

Basic Functions
# Simple function — no parameters
function Get-Greeting {
    Write-Host "Hello from a function!"
}
Get-Greeting # call it
Hello from a function!

# Function with parameters
function Get-Square {
    param(
        [int]$Number
    )
    return $Number * $Number
}
Get-Square -Number 7 # 49

# Multiple parameters with defaults
function Get-FullName {
    param(
        [string]$FirstName,
        [string]$LastName = "Doe" # default value
    )
    "$FirstName $LastName"
}
Get-FullName -FirstName "Alice" # "Alice Doe"
Get-FullName -FirstName "Bob" -LastName "Smith" # "Bob Smith"

Advanced Functions with Validation

Add parameter validation to catch bad input early:

Functions with Validation
function Set-LogLevel {
    param(
        [ValidateSet('Info', 'Warning', 'Error')]
        [string]$Level = 'Info',

        [ValidateRange(1, 100)]
        [int]$MaxLines = 50,

        [Parameter(Mandatory)]
        [string]$LogPath # required — will prompt if missing
    )
    Write-Host "Log: $LogPath | Level: $Level | Max: $MaxLines"
}

# Tab-complete will show 'Info', 'Warning', 'Error' for -Level!
Set-LogLevel -LogPath "C:\app.log" -Level "Warning"

Writing Your First Real Script

Let's put it all together with a practical example — a script that checks disk space and warns if it's low:

disk-check.ps1 — A Complete Script
# disk-check.ps1
# Checks disk space on specified drives and warns if low

function Get-DiskStatus {
    param(
        [string[]]$Drives = @('C'),
        [int]$WarnThresholdGB = 10
    )

    foreach ($drive in $Drives) {
        $disk = Get-PSDrive -Name $drive -ErrorAction SilentlyContinue

        if (-not $disk) {
            Write-Host "Drive $drive: not found." -ForegroundColor Yellow
            continue
        }

        $freeGB = [math]::Round($disk.Free / 1GB, 1)
        $totalGB = [math]::Round(($disk.Free + $disk.Used) / 1GB, 1)
        $pctFree = [math]::Round($freeGB / $totalGB * 100, 0)

        if ($freeGB -lt $WarnThresholdGB) {
            $color = "Red"
            $status = "⚠ LOW"
        } else {
            $color = "Green"
            $status = "OK"
        }

        Write-Host ("Drive {0}: {1}GB free of {2}GB ({3}%) [{4}]" -f
            $drive, $freeGB, $totalGB, $pctFree, $status
        ) -ForegroundColor $color
    }
}

# Run it!
Get-DiskStatus -Drives @('C', 'D') -WarnThresholdGB 20
Drive C: 124.5GB free of 476.9GB (26%) [OK]
Drive D: 8.2GB free of 500.0GB (2%) [⚠ LOW]
Saving scripts: Save PowerShell code as .ps1 files. Run them with .\myscript.ps1. If you get an execution policy error, run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser once to allow local scripts.

🧪 Try It Yourself

  1. Write an if/else that checks if a number is even or odd (hint: use % — modulo)
  2. Write a foreach loop that goes through an array of your favorite colors and prints each one
  3. Write a function called Get-Greeting that takes a -Name parameter and says "Hello, [Name]!"
  4. Copy the disk-check script above into a .ps1 file and run it with your drives
  5. Modify the disk-check to also log results to a text file using Add-Content

🎉 Congratulations — You've Completed the Beginner Track!

You now know the fundamentals of PowerShell:

  • Opening PowerShell, navigating the file system, and using the console
  • Variables and all the main data types (strings, numbers, arrays, hashtables)
  • Cmdlets, the Verb-Noun pattern, Get-Help, Get-Command, and Get-Member
  • The pipeline with Where-Object, Select-Object, Sort-Object, and ForEach-Object
  • Control flow with if/else, switch, loops (for, foreach, while), and functions

Next steps: Check the Command Reference to explore more cmdlets, and watch for upcoming Intermediate lessons covering file operations, error handling, regular expressions, and more.