{"id":1042,"date":"2014-07-08T00:01:00","date_gmt":"2014-07-08T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/07\/08\/getting-to-know-foreach-and-foreach-object\/"},"modified":"2014-07-08T00:01:00","modified_gmt":"2014-07-08T00:01:00","slug":"getting-to-know-foreach-and-foreach-object","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/getting-to-know-foreach-and-foreach-object\/","title":{"rendered":"Getting to Know ForEach and ForEach-Object"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Learn the differences between <strong>ForEach<\/strong> and <strong>ForEach-Object<\/strong> in Windows PowerShell.<\/span><\/p>\n<p>Honorary Scripting Guy and Windows PowerShell MVP, <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/tag\/boe-prox\/\" target=\"_blank\">Boe Prox<\/a>, here today filling in for my good friend, The Scripting Guy. Today I am going to talk about some differences between using <b>ForEach<\/b> and using <b>ForEach-Object<\/b> in day-to-day scripting activities.<\/p>\n<p>There are times when you are unable to make use of a cmdlet that has built-in pipeline support, such as something like this:<\/p>\n<p style=\"margin-left:30px\">Get-ChildItem &ndash;File &ndash;Filter &ldquo;*.TMP&rdquo; | Remove-Item &ndash;Verbose<\/p>\n<p>To get around this, we can make use of some other capabilities of Windows PowerShell by using <b>ForEach<\/b> or <b>ForEach-Object<\/b> to iterate through collections and to perform an action against each item in the collection. Each of these approaches can let you run through a collection and then perform actions in a script block. What you may not know is that each cmdlet has two approaches to how they take and handle the collections.<\/p>\n<p>Let&#039;s take a look at <b>ForEach-Object<\/b> and see what it is about. This cmdlet has a couple of aliases that may seem familiar to you:<\/p>\n<p style=\"margin-left:30px\">Get-Alias &ndash;Definition ForEach-Object<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-1.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Wait a second! Why in the world are there two <b>ForEach<\/b> options in Windows PowerShell? This is an excellent question, and fortunately, I have an answer. When you are piping input into <b>ForEach<\/b>, it is the alias for <b>ForEach-Object<\/b>. But when you place <b>ForEach<\/b> at the beginning of the line, it is a Windows PowerShell statement.<\/p>\n<p><b>ForEach-Object<\/b> is best used when sending data through the pipeline because it will continue streaming the objects to the next command in the pipeline, for example:<\/p>\n<p style=\"margin-left:30px\">ForEach-Object -InputObject (1..1E4) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_<\/p>\n<p style=\"margin-left:30px\">} | Measure-Object<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">Count&nbsp;&nbsp;&nbsp; : 10000<\/p>\n<p style=\"margin-left:30px\">Average&nbsp; :<\/p>\n<p style=\"margin-left:30px\">Sum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :<\/p>\n<p style=\"margin-left:30px\">Maximum&nbsp; :<\/p>\n<p style=\"margin-left:30px\">Minimum&nbsp; :<\/p>\n<p style=\"margin-left:30px\">Property :<\/p>\n<p>You cannot do the same thing with <b>ForEach () {}<\/b> because it will break the pipeline and throw error messages if you attempt to send that output to another command.<\/p>\n<p style=\"margin-left:30px\">ForEach ($i in (1..1E4)) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $i<\/p>\n<p style=\"margin-left:30px\">} | Measure-Object<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">At line:3 char:3<\/p>\n<p style=\"margin-left:30px\">+ } | Measure-Object<\/p>\n<p style=\"margin-left:30px\">+&nbsp;&nbsp; ~<\/p>\n<p>Note that an empty pipe element is not allowed.<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : ParserError: (:) [], ParentContainsErrorRecordException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : EmptyPipeElement<\/p>\n<p>You would have to save all of the output that is being process by <b>ForEach<\/b> to a variable and then pipe it to another cmdlet, for example:<\/p>\n<p style=\"margin-left:30px\">$Data = ForEach ($i in (1..1E4)) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $i<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p style=\"margin-left:30px\">$Data | Measure-Object<\/p>\n<p>The fact that now we have totally broken the pipeline becomes more apparent after this. Not only do we have to stop the pipeline to begin processing the data, we cannot even send that data to the pipeline from the statement without first collecting the output into a variable and then sending it down the pipeline.<\/p>\n<p>This is very important if you plan to use the data in another command through the pipeline. It is important to note another difference that these options share, which is performance vs. memory consumption.<\/p>\n<p>The <b>ForEach<\/b> statement loads all of the items up front into a collection before processing them one at a time. <b>ForEach-Object<\/b> expects the items to be streamed via the pipeline, thus lowering the memory requirements, but at the same time, taking a performance hit. Following are a couple of tests to highlight the differences between these:<\/p>\n<p style=\"margin-left:30px\">$time = (Measure-Command {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; 1..1E4 | ForEach-Object {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $_<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">}).TotalMilliseconds<\/p>\n<p style=\"margin-left:30px\">&nbsp;[pscustomobject]@{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Type = &#039;ForEach-Object&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Time_ms = $Time<\/p>\n<p style=\"margin-left:30px\">&nbsp;}<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">$Time = (Measure-Command {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; ForEach ($i in (1..1E4)) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $i<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">}).TotalMilliseconds<\/p>\n<p style=\"margin-left:30px\">&nbsp; [pscustomobject]@{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Type = &#039;ForEach_Statement&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Time_ms = $Time<\/p>\n<p style=\"margin-left:30px\">&nbsp;}<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-2.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>As expected, the <b>ForEach<\/b> statement, which allocates everything to memory before processing, is the faster of the two methods. <b>ForEach-Object<\/b> is much slower. Of course, the larger the amount of data, the more risk you have of running out of memory before you are able to process all of the items. So be sure to take that into consideration.<\/p>\n<p>To throw another curve ball into this, check out this alternate approach to <b>ForEach-Object<\/b>. This time, we&#039;ll use the <b>InputObject<\/b> parameter (this is the parameter used in the pipeline process):<\/p>\n<p style=\"margin-left:30px\">$Time = (Measure-Command {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; ForEach-Object -InputObject (1..1E4) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $_<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">}).TotalMilliseconds<\/p>\n<p style=\"margin-left:30px\">&nbsp;[pscustomobject]@{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Type = &#039;ForEach-Object_Param&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Time_ms = $Time<\/p>\n<p style=\"margin-left:30px\">&nbsp;}<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Wow, that was fast! Why am I not talking this up instead of focusing on <b>ForEach<\/b>? Although this seems like the fastest of the three approaches, the major (yes, major!) issue is that we are being deceived into thinking that it just processed everything in an amazing amount of time. But the fact is that all we did was pass the entire collection to the script block one time&mdash;and that was it.<\/p>\n<p style=\"margin-left:30px\">ForEach-Object -InputObject (1..1E4) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.GetType().FullName<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-4.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Well, it was worth a shot to squeeze a little more speed out of this. But in the end, we get something that is completely unusable&mdash;even if we did want to send it down the pipeline.<span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n<p><b>ForEach-Object<\/b> also allows us to specify <b>Begin<\/b>, <b>Process<\/b>, and <b>End<\/b> script blocks that we can use (similar to an advanced function) to set up our environment, process each item, and then do something (such as clean up at the end of the command).<\/p>\n<p style=\"margin-left:30px\">Get-ChildItem -Force | ForEach-Object -Begin {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Write-Verbose &quot;Begin block&quot; -Verbose<\/p>\n<p style=\"margin-left:30px\">} -Process {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; If ($_.length -gt 555) {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write-Verbose &quot;Process block&quot; -Verbose<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $_<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">} -End {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; Write-Verbose &quot;End block&quot; -Verbose<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-5.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-7-8-14-5.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Here you see that the <b>Begin<\/b> block kicks off first, followed by all of the items that I am processing and filtering, with the <b>End<\/b> block being processed last. If I wanted, I could then pass this to another cmdlet, such as <b>Export-CSV<\/b>. You couldn&rsquo;t come close to doing this type of action by using the <b>ForEach<\/b> statement.<\/p>\n<p>So which one do you use? Well, the answer is, &ldquo;It depends.&rdquo;<\/p>\n<p>You can iterate through a collection of items by using either the <b>ForEach<\/b> statement or the <b>ForEach-Object<\/b> cmdlet.<\/p>\n<ul>\n<li><b>ForEach<\/b> is perfect if you have plenty of memory, want the best performance, and do not care about passing the output to another command via the pipeline.<\/li>\n<li><b>ForEach-Object<\/b> (with its aliases <b>%<\/b> and <b>ForEach<\/b>) take input from the pipeline. Although it is slower to process everything, it gives you the benefit of <b>Begin<\/b>, <b>Process<\/b>, and <b>End<\/b> blocks. In addition, it allows you to stream the objects to another command via the pipeline.<\/li>\n<\/ul>\n<p>In the end, use the approach that best fits your requirement and the capability of your system.<\/p>\n<p>Follow the Scripting Guys on&nbsp;<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send an email to the Scripting Guys at&nbsp;<a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the&nbsp;<a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>.<span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n<p><span style=\"font-size:12px\"><b>Boe Prox,&nbsp;<\/b>Windows PowerShell MVP and Honorary Scripting Guy<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn the differences between ForEach and ForEach-Object in Windows PowerShell. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. Today I am going to talk about some differences between using ForEach and using ForEach-Object in day-to-day scripting activities. There are times when you [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[162,51,56,3,4,45],"class_list":["post-1042","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-boe-prox","tag-getting-started","tag-guest-blogger","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn the differences between ForEach and ForEach-Object in Windows PowerShell. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. Today I am going to talk about some differences between using ForEach and using ForEach-Object in day-to-day scripting activities. There are times when you [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1042","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=1042"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1042\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=1042"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=1042"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=1042"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}