Powershell – Loops

Automating repetitive tasks is what scripting is all about.  Therefore, each scripting language needs at least one method for cycling, or looping through a block of instructions.

PowerShell provides a rich variety of looping techniques.  However, because loops can go spectacularly wrong, I recommend you test a simple PowerShell 'foreach' loop before graduating to more complex constructions in your production scripts.

Examples of the PowerShell Foreach Loop

The PowerShell 'Foreach' loop is more complex, and has more arguments than the 'for' and 'Do While' loops.  The key feature is that loop interrogates an array, known as a collection.  It then applies a {Statement Block} to each iteration.  In addition to the position and the type of bracket, observe the tiny, but crucial keyword - 'in'.

The secret of PowerShell loops is to absorb each element of this syntax:

Foreach ($item in $array_collection) {command_block}.

[tab:Example 1]

Example 1: PowerShell Foreach with Pure Math

# Simple PowerShell foreach statement
foreach ($number in 1,2,3,4,5,6,7,8,9,10) { $number * 7}
# PowerShell Foreach Example
Clear-Host
foreach ($number in 1..10 ) { $number * 7}
$NumArray = (1,2,3,4,5,6,7,8,9,10)
foreach ($number in $NumArray ) { $number * 7}
foreach ($number in 1,2,3,4,5,6,7,8,9,10) { $number * 7}
$NumArray = (1..10)
foreach ($number in $numArray ) { $number * 7}

Learning Points

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

Note 2:  (1..12) is a convenient method of representing a sequence.

[tab:Example 2]

Example 2: PowerShell Foreach to Display Files

In Example 2 we are going to transition from the explicit ($Item in Collection) {Block Statement} to:
Input stuff 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 this script will work without modification on 99.9% of computers.

Example 2a Explicit Foreach Get-ChildItem

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

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

As usual with scripting PowerShell has dozens of techniques to achieve the same outcome.

The key difference in this example is how the foreach 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 3:  To help modify my scripts to suit your project I have introduced a $Path variable.

[tab:Example 3]

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 4: This example uses the same 'If clause' as example 3a, its purpose is to filter just .txt files.

[tab:Example 4]

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, in this case the foreach loop.

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)}

Example 4b - 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}

[tab:Example 5]

Example 5 - Active Directory

This example conforms to the PowerShell ForEach (condition) {Code Block}; however, there is a preamble of 16 lines where the script connect to Active Directory.  Moreover, the {Code Block} is spread over several lines.

N.B. Find $Dom on line 7 and change the value to that of your domain, including the extension.

# ForEach_AD.ps1
# Illustrates using PowerShell ForEach loop to interrogate AD
# IMPORTANT change $Dom 'value'
# Author: Guy Thomas
#
$Dom = 'LDAP://DC=YourDom;DC=YourExt'
$Root = New-Object DirectoryServices.DirectoryEntry
clear-Host

# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root

# Filter the users with -like "CN=Person*". Note the ForEach loop
$adobj= $selector.findall() `
| where {$_.properties.objectcategory -like "CN=Person*"}
ForEach ($person in $adobj)
{
$prop=$person.properties
Write-host "First name: $($prop.givenname) " `
"Surname: $($prop.sn) User: $($prop.cn)"
}
write-host "`nThere are $($adobj.count) users in the $($root.name) domain"

Learning Points

Note 5: ` on its own means word-wrap.  `n means new line and `t means tab.

[tab:For Loop]

PowerShell For Loop (Also know as the for statement)

One use of the PowerShell 'For loop' is to iterate an array of values and then work with a subset of these values.  Should you wish to cycle through all the values in your array, consider using a foreach construction.

Here is the syntax:

for (<init>; <condition>; <repeat>) {<command_block>}

Example

for ( $i = 7; $i -le 84; $i+=7 ) { $i }

[tab:Loop Trick]

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 * 7}) | set-variable 7x
$7x
# Option research properties by removing # on the next line
# $7x |Get-Member

Dejan Milic's Method (Better)

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

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

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

[tab:END]

SOURCE

LINK

LANGUAGE
ENGLISH