PowerShell ForEach Loops

PowerShell ForEach Operator Loops

For me, one of the most magical aspects of scripting is how simple commands loop through a set of instructions and then produces results – in a flash.  Sometimes this magic is hidden, for example Get-Process implies looping as it returns all the running processes, in other cases we need ForEach to explicitly step through the items.

My mission on this page is to give you simple examples of how to master the PowerShell foreach loop.  As you become more proficient in PowerShell, so the instructions grow in complexity.

Topics for PowerShell’s ForEach Loop

 ♣

Examples of the PowerShell ForEach Loop

The ForEach loop is used in situations where we need to work with one object at a time.  Each loop interrogates an array, which is also known as a collection.  During each cycle the foreach operator executes a {Statement Block} on each individual item.

Note that when you work with PowerShell examples the brackets always carry hidden messages.  Observe that the (array is enclosed by parenthesis brackets), whereas the block statement is always contained in {Curly brackets}.

One more tiny, but crucial, component of the PowerShell ForEach loop is ‘in’.

The secret of understanding this PowerShell loop syntax is to grasp each element of this syntax:
ForEach ($item in $array_collection) {command_block}.

Example 1: PowerShell ForEach with Pure Math

The math task is to reproduce the 13 times table.  PowerShell showcases four variations of ForEach loops, each of which achieves this multiplication.

# Simple PowerShell ForEach statement
ForEach ($number in 1,2,3,4,5,6,7,8,9,10) { $number * 13}

# PowerShell ForEach Example
Clear-Host
ForEach ($number in 1..10 ) { $number * 13}

Clear-Host
$NumArray = (1,2,3,4,5,6,7,8,9,10)
ForEach ($number in $NumArray ) { $number * 13}

Clear-Host
$NumArray = (1..10)
ForEach ($number in $numArray ) { $number * 13}

Learning Points

Note 1: By creating these four variations, my aim is to give you both perspective and experience of the pure, but simple PowerShell foreach statement.

Note 2: Foreach is at the start of its command line (unlike ForEach-Object).

Note 3: PowerShell’s ‘ForEach’ is more complex, and has more arguments than the ‘for’ and ‘Do While’ techniques for stepping through a collection of items. 

Guy Recommends:  A Free Trial of the Network Performance Monitor (NPM)Review of Orion NPM v11.5 v11.5

SolarWinds’ Network Performance Monitor will help you discover what’s happening on your network.  This utility will also guide you through troubleshooting; the dashboard will indicate whether the root cause is a broken link, faulty equipment or resource overload.

What I like best is the way NPM suggests solutions to network problems.  Its also has the ability to monitor the health of individual VMware virtual machines.  If you are interested in troubleshooting, and creating network maps, then I recommend that you try NPM now.

Download a free trial of Solarwinds’ Network Performance Monitor

Example 2a:  PowerShell ForEach to Display Files

In Example 2 we are going to transition from the explicit ($Item in Collection) {Block Statement} to:
Input files using Get-ChildItem, then pipe (|) the output into a {Block Statement}.

Get-ChildItem is just the vehicle for us to investigate aspects of the PowerShell foreach loop.  I chose the root of the C: drive simply because I want this example script to work without modification on most of computers.

Example 2a Explicit ForEach Get-ChildItem

# PowerShell ForEach File Example
Clear-Host
ForEach ($file in Get-ChildItem  C:\)
{
$file.name
}

Note 4: I say again, Get-ChildItem is just a vehicle to showcase ForEach.

Example 2b ForEach Piping | Directly Into the {block statement}

As usual PowerShell has dozens of techniques to achieve the same outcome.  The key difference in this example is how the foreach loop works with input from PowerShell’s piping (|).  The point is that there is no need for an explicit ($Item in $Collection) clause.

# PowerShell ForEach File Example
Clear-Host
$Path = "C:\Windows\System32\*.dll"
Get-ChildItem $Path | ForEach {
Write-Host $_.Name
}

Learning Points
Note 5:
 To help modify my scripts to suit your project, I have introduced a $Path variable.  See more on the $_. construction.

Engineer's Toolset v10Guy Recommends: SolarWinds Engineer’s Toolset v10

This Engineer’s Toolset v10 provides a comprehensive console of 50 utilities for troubleshooting computer problems.  Guy says it helps me monitor what’s occurring on the network, and each tool teaches me more about how the underlying system operates.

There are so many good gadgets; it’s like having free rein of a sweetshop.  Thankfully the utilities are displayed logically: monitoring, network discovery, diagnostic, and Cisco tools.  Try the SolarWinds Engineer’s Toolset now!

Download your fully functional trial copy of the Engineer’s Toolset v10

Example 3a: A More Complex ForEach Example

This pair of examples are just like the above, but introduce slightly more complex scripting.  Example 3a contains Foreach with a ($Item in Collection) clause; please contrast with example 3b which exploits the ability of foreach to receive input via the pipe (|).

# PowerShell ForEach loop to display files in C:\Program files
$Path = "C:\Program Files\"
"{0,10} {1,-24} {2,-2}" -f `
" Size", "Last Accessed", "File Name "
ForEach ($file in Get-ChildItem  $Path -recurse -force)
{If ($file.extension -eq ".txt")
     {
     "{0,10} {1,-24} {2,-2}" -f `
     $file.length, $file.LastAccessTime, $file.fullname
     }
}

Example 3b ForEach piping | directly into the {block statement}

# PowerShell ForEach loop piping into block statement
Clear-Host
$Path = "C:\Program Files\"
Get-ChildItem  $Path -recurse -force | ForEach {
If ($_.extension -eq ".txt") {
Write-Host $_.fullname
    }
}

Note 6: This example uses the same ‘If clause’ as example 3a, its purpose is to filter just .txt files.

Example 4: PowerShell ForEach Loop With WMI

Once again, observe the basic structure: ForEach (x in y) {script block}.  Where you have more than one drive you need a loop, another job for ForEach.

Basic Example

$disk= Get-WmiObject Win32_LogicalDisk
ForEach ( $drive in $disk ) { "Drive = " + $drive.Name}

Example Incorporating Extra Maths

# ForEach example to display the partitions size [GB]
$disk= Get-WmiObject Win32_LogicalDisk
"Drive Ltr: Size [GB]"
ForEach ( $drive in $disk ) { "Drive = " + $drive.Name + `
" Size = " + [int]($drive.Size/1073741824)}

Guy Recommends: Free WMI Monitor for PowerShellSolarwinds Free WMI Monitor for PowerShell

Windows Management Instrumentation (WMI) is one of the hidden treasures of Microsoft’s operating systems.  Fortunately, SolarWinds have created a Free WMI Monitor so that you can discover these gems of performance information, and thus improve your PowerShell scripts.

Take the guess work out of which WMI counters to use when scripting the operating system, Active Directory, or Exchange Server. Give this WMI monitor a try – it’s free.

Download your free copy of WMI Monitor

Example 4: Another Simple ForEach Using Get-Process

Here is an example using Get-Process.  In essence this simple script filters the running processes.  Please feel free to modify.  Once again, note the tiny word ‘in’.

# PowerShell example listing processes beginning with Task*
Clear-Host
ForEach ($T in Get-Process Task*) {$T.Name}

PowerShell Loop Output Trick

I have not found it possible to pipe input into loops.  Obtaining output was nearly as difficult, however, I have discovered this trick to assign the output to a variable, which we can then manipulate.

$NumArray = (1..12)
$(ForEach ($number in $NumArray ) { $number * 13}) | set-variable 13x
$13x
# Option research properties by removing # on the next line
# $13x |Get-Member

Dejan Milic’s Method (Better)

$NumArray = (1..12)
$13x = @()
ForEach ($number in $NumArray ) { $13x+=$number * 13}
$13x

/\/\o\/\/’s  Method (Fantastic)

$13x = 1..12 | % {$_ * 13 }
$13x

I (Guy) envy /\/\o\/\/’s ability to write tight code.  That % sign means ‘foreach’. If you (readers) see anything on the internet by /\/\o\/\/, then you can be sure that it’s top draw code.

For Even More Information about ForEach Loops – Check About_ForEach

Clear-Host
Get-Help About_foreach

PowerShell’s ForEach-Object Cmdlet

The ForEach-Object cmdlet specializes in controlling loops which accept pipeline input.  One of this cmdlet’s interesting features is displaying start and finish times.  It achieves this courtesy of the -begin and -end parameters.

Confusion: What adds to the confusion is that the ForEach-Object cmdlet has an alias of foreach.  My tip is watch out for the use of ‘in’, which is used by foreach the statement, the operator, but not by Foreach the alias for the cmdlet.  The key technical difference is the ForEach-Object does not have to be the first item in the statement, and more importantly, it accepts | (pipelining).

Engineer's Toolset v10Guy Recommends: SolarWinds Engineer’s Toolset v10

This Engineer’s Toolset v10 provides a comprehensive console of 50 utilities for troubleshooting computer problems.  Guy says it helps me monitor what’s occurring on the network, and each tool teaches me more about how the underlying system operates.

There are so many good gadgets; it’s like having free rein of a sweetshop.  Thankfully the utilities are displayed logically: monitoring, network discovery, diagnostic, and Cisco tools.  Try the SolarWinds Engineer’s Toolset now!

Download your fully functional trial copy of the Engineer’s Toolset v10

Example 5: PowerShell ForEach-Object Cmdlet

In addition to plain foreach, which is an operator, PowerShell has a ForEach-object cmdlet.

The purpose of this script is to interrogate the application event log, then employ Out-File to write the messages to disk.

$LogPath = "C:\temp\application.txt"
$i = 0
$LogType = "Application"
$Logs = Get-Eventlog -Logname $LogType -newest 500
$Logs | ForEach-Object {
Out-File -filepath $LogPath -append -Inputobject $_.message; $i++
}
Write-Host "$i $LogType logs written to $LogPath"

Note 7: The key is element is piping the $Logs into ForEach-Object, then referencing $_.message

Note 8: You may wish to amend the values for $LogPath and $LogType.

$LogPath = "C:\temp\application.txt"
$i = 0
$LogType = "Application"
$Logs = Get-Eventlog -Logname $LogType -newest 500
$Logs | ForEach-Object -begin {Get-Date} -process {
Out-File -filepath $LogPath -append -Inputobject $_.message; $i++
} -end {Get-Date}
Write-Host "$i $LogType logs written"

Note 9: Observe how the -begin and -end parameters write date stamps.

More Information on ForEach-Object

Clear-Host
Get-Help ForEach-Object

Note 10: The ForEach-Object has this alias: % (Percent sign)

More on the differences between 'ForEach-Object' and 'ForEach' Loops »

Comparison of PowerShell ForEach Operator with ForEach-Object Cmdlet

It surprised me that the simple ForEach operator was an order of magnitude faster than the ForEach-Object cmdlet.

# Comparison of PowerShell ForEach operator and ForEach-object cmdlet
Clear-Host
$BigNum = 1..10000
$GuyMuliplier = 7777
# ForEach Operator
Write-Host "ForEach operator. Note this command uses word 'in'."
Measure-Command {ForEach($item in $BigNum) {$item*$GuyMultiplier}} |
Format-Table Milliseconds -auto
# ForEach-Object
Write-Host "ForEach-Object Cmdlet. In this code, note the pipe"
Measure-Command {$BigNum | ForEach-Object {$_ * $GuyMultiplier} } |
Format-Table Milliseconds -auto

Note 11: This script uses Measure-Command to compare PowerShell’s two looping techniques.

Note 12: Incidentally, if a line ends in (|), you don't need to word-wrap with the backtick (`)

See more on PowerShell Measure-Command »

Summary of PowerShell ForEach Loops

The secret of understanding the PowerShell ForEach loop is to study the type of bracket.  For example when defining the constructions elements, (use parenthesis) for the condition and {use braces} for the command block.

In addition to Take the time to master loops, and thus automate your repetitive tasks.

If you like this page then please share it with your friends

 


See more Windows PowerShell examples

PowerShell Home   • Foreach loops   • PowerShell Foreach   • Foreach-Object cmdlet

Syntax   • Variables   • -whatIf   • -ErrorAction   • Windows 8 PowerShell   • Free CSV Import Tool

PowerShell Functions   • [System.Math]   • Get-Credential   • Windows PowerShell   • PowerShell 3.0

Please email me if you have a better example script.  Also please report any factual mistakes, grammatical errors or broken links, I will be happy to  correct the fault.