• subscribe
September 26, 2008 12:00 AM

Iterating Through Collections with PowerShell's foreach Loops

Lesson 1 in the PowerShell 201 series explores how to use the foreach statement and ForEach-Object cmdlet
Windows IT Pro
InstantDoc ID #99873
Executive Summary: The Windows PowerShell 101 series introduced you to Microsoft’s Windows PowerShell environment and the scripting language it supports. The lessons in that series describe concepts that provide a foundation for using PowerShell and writing PowerShell statements. The PowerShell 201 series digs deeper into those concepts and explains the PowerShell structures that let you fully leverage PowerShell. In Lesson 1, you'll learn how to use the foreach statement and the ForEach-Object cmdlet to iterate through collections.

To fully leverage the power of Windows PowerShell, you need to know how to use a foreach loop to iterate through collections such as a string array or a list of Windows services. PowerShell provides two types of foreach loops: the foreach statement and the ForEach-Object cmdlet. Although you can obtain the same results with both types of loops, they differ in several important respects. In this lesson, I’ll explain the differences and demonstrate how to use the foreach statement and the ForEach-Object cmdlet. Note that this and subsequent lessons in the PowerShell 201 series build on concepts explained in the PowerShell 101 series. (See the Learning Path for the lessons in that series.)

The foreach Statement
The foreach statement loops through the elements in a collection. The loop runs one time for each element, executing a block of statements called a script block. To create a foreach loop, you must define the collection that you’ll loop through, a variable to hold each element in that collection, and the script block that runs each time you step through the collection.

Let’s take a look at an example to see how this works. The following command declares the $birds variable and initializes it with a string array, then uses the variable in a foreach statement:

$birds = "owl","crow","robin","wren","jay" foreach ($bird in $birds) { "$bird = " + $bird.length }

The foreach statement begins with the foreach keyword, followed by a set of parentheses that enclose three components ($bird in $birds). The first component is the element variable, which you define specifically to use in the foreach statement. In this case, the element variable is $bird, but you can name the variable whatever you want, as long as you adhere to PowerShell’s naming conventions. The element variable holds the collection’s current value as the statement loops through the collection. For example, the $bird variable’s value is owl in the first loop, crow in the second loop, and so on.

Learning Path
Windows it pro resources
To read the “PowerShell 101” series, go to
“PowerShell 101, Lesson 1,” InstantDoc ID 97742
“PowerShell 101, Lesson 2,” InstantDoc ID 97959
“PowerShell 101, Lesson 3,” InstantDoc ID 98177
“PowerShell 101, Lesson 4,” InstantDoc ID 98447
“PowerShell 101, Lesson 5,” InstantDoc ID 98793
“PowerShell 101, Lesson 6,” InstantDoc ID 99104

The second component in the parentheses is the keyword in. Use this just as is. The third element is the collection itself, which in this case is accessed through the $birds variable.

Next comes a set of braces. The braces enclose the script block that executes whenever a loop runs. In this example, the block contains only one statement—"$bird = " + $bird.length—that creates a simple string, which is output to the console. In this code, the $bird variable retrieves the collection value, and the Length property retrieves the number of characters in that value.

The command returns the results

owl = 3
crow = 4
robin = 5
wren = 4 jay = 3

Although this example includes only one statement in the script block, you can include as many statements as necessary. For example, here’s a script block that contains three statements:

$count = 0
$birds = "owl","crow","robin", `
  "wren","jay"
foreach ($bird in $birds)
{
  $count += 1
  "$bird = " + $bird.length
Write-Host
}
"Total number of birds is $count."

The first statement in the script block increments the $count variable by 1. (The $count variable is defined in the first line and is used to track the running total of collection elements.) The second statement creates the string and outputs it to the console, as you saw in the last example. The third statement is a Write-Host cmdlet, which simply adds a blank line to the output.

When each loop runs, all three statements in the script block run. However, the code after the script block runs only once, after the last loop has completed. This code uses $count within the outputted text. In this case, the value in $count is 5. This is the value assigned to that variable during the last loop, as shown in the results

owl = 3


crow = 4


robin = 5


wren = 4


jay = 3


Total number of birds is 5.

Although the preceding commands assign the collection (a string array) to a variable, you don’t have to take this approach. You can define your collection directly within the foreach statement, and you can define a collection made up of other object types, as in

foreach ($svc in Get-Service)
{  $svc.name + ": " +  $svc.canstop.tostring().toupper()}

In this code, the third component in the parentheses is Get-Service. This cmdlet returns a collection of objects, one object for each service on the local machine. A service object is assigned to the $svc variable each time through the loop. In the loop, the foreach statement uses $svc to retrieve the service’s name (through the service object’s Name property) and appends a colon to it. Next, foreach uses $svc to access the service object’s CanStop property, which returns a Boolean value that specifies whether the service can be stopped once it has started. Finally, the foreach statement calls the ToString and ToUpper methods to format that value. You must first convert the CanStop property's value to a string with the ToString method before uppercasing it with the ToUpper method because the ToUpper method is available only to string values. If you don’t want to convert the results to uppercase, you don’t need to include the ToString method or the ToUpper method. Figure 1 shows the results.

Note that when you reference an object’s methods and properties, their names are case insensitive. For example, you can call the ToString method by using letters that are all lowercase (as I’ve done in my examples), all uppercase, or mixed case.

Continue to page 2



ARTICLE TOOLS

Comments
  • JOHN
    3 years ago
    Apr 09, 2009

    I like to print out the articles to put in a binder so I have all of the Powershell series in one place, but the Figures turn out to be useless since the article prints without them and they are too small. Also, I know that magazines love to play with graphics to make themselves look classy, but NOTHING is better and easier on the eyes than black ink on white paper. The white on blue looks great on my monitor, but not so hot on the printed page.

You must log on before posting a comment.

Are you a new visitor? Register Here