PowerShell Basics - Loops

Author by Mitchell Grande

The final article in the PowerShell basics series will look at PowerShell loops and how to use them to interact with multiple objects.  We'll specifically use the Foreach-Object command to iterate through a group of results.  Finally, we’ll review command aliases to help you read and write PowerShell more efficiently.

Foreach-Object Overview

The Foreach-Object command is the primary way to act on multiple objects in a result at once.  In previous articles, we looked at how you can filter results using the Where-Object command, and we even used the pipe operator to send the results of one command to another command for additional processing.  However, more complex operations don't fit in a single piped operation.  This is where loops and the Foreach-Object command come in.

To use Foreach-Object, you need two components.  First, you need to pipe some data into it.  This could be an existing variable or another command on the left side of the pipe operator, "|".  Second, you need a script block, wrapped in curly braces, { and }, that does the actual processing of the data.  As a simple example, this script will print out the numbers 1 - 10:

$numbers = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
$numbers | ForEach-Object {
    Write-Host $_
}

Notice how within the script block, the $_ variable is used.  This is a special variable that automatically references the current object within the loop.  When the $numbers variable is passed to Foreach-Object, $_ refers to each of the numbers in succession.  For a slightly more complex example, this script will print out the name and login name for all of the users in Active Directory:

Get-ADUser -Filter * | Foreach-Object {
    Write-Host $_.Name
    Write-Host $_.SamAccountName
}

In this script, $_ refers to the current user being acted on within the loop. The entire script block executes one time for each found user, with $_ referring to each individual user as it runs.

Sample Scripts

With the basics out of the way, here are some sample scripts that demonstrate how to use the Foreach-Object command and some good uses cases for it:

#Get the contents of C:\Temp and print each file name and size
Get-ChildItem -Path "C:\Temp" | ForEach-Object {
    $ItemPath = $_.FullName
    $ItemSize = $_.Length
    Write-Host "$ItemPath is $ItemSize bytes"
}

#Find all servers in the domain and use Test-Computer to see if they are responding to ping
$Servers = Get-ADComputer -Filter {OperatingSystem -like "*Server*"}
$Servers | Foreach-Object {
    $ServerName = $_.DnsHostname
    if (Test-Connection -ComputerName $ServerName -Count 1 -Quiet) {
        Write-Host "$ServerName responded to ping!"
    } else {
        Write-Host "$ServerName did not respond to ping!"
    }
}

#Find mailboxes with a primary address of @example.com and grant ArchiveUser full access to them
Get-Mailbox | Where-Object {$_.PrimarySmtpAddress -like '*@example.com'} | Foreach-Object {
    $_ | Add-MailboxPermission -User "ArchiveUser" -AccessRights FullAccess -InheritanceType All
}

The final example here shows how you can combine Where-Object and Foreach-Object to only take action on a specific set of objects.

Command Aliases

Many common PowerShell commands have aliases that can be used instead of the full command name.  The most common ones are for Where-Object and Foreach-Object.  Instead of Where-Object, you can simply use a question mark, "?", and instead of Foreach-Object, you can use a percent sign, "%".  The final example from above could be rewritten to:

#Find mailboxes with a primary address of @example.com and grant ArchiveUser full access to them
Get-Mailbox | ? {$_.PrimarySmtpAddress -like '*@example.com'} | % {
    $_ | Add-MailboxPermission -User "ArchiveUser" -AccessRights FullAccess -InheritanceType All
}

This is functionally identical to the original version but is a little quicker to type and possibly easier to read.  Additionally, other common commands have the following aliases by default:

  • Get-ChildItem -> gci
    • List the contents of the current folder
  • Sort-Object -> sort
    • Sort a list of objects
  • Select-Object -> select
    • Select specific properties of an object
  • Format-List -> fl
    • Print out an object in list format
  • Format-Table -> ft
    • Print out an object in table format

A full list of command aliases is available by running the Get-Alias command.

This article concludes the PowerShell basics series.  If you weren't already, hopefully you're now a little more confident in being able to read and write PowerShell code.

Author

Mitchell Grande

Systems Engineer

Tags in this Article