{"id":53823,"date":"2009-05-05T23:19:00","date_gmt":"2009-05-05T23:19:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/05\/05\/hey-scripting-guy-how-can-i-loop-through-collections-with-windows-powershell\/"},"modified":"2009-05-05T23:19:00","modified_gmt":"2009-05-05T23:19:00","slug":"hey-scripting-guy-how-can-i-loop-through-collections-with-windows-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-loop-through-collections-with-windows-powershell\/","title":{"rendered":"Hey, Scripting Guy! How Can I Loop Through Collections with Windows PowerShell?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> <\/H2>\n<P>Hey, Scripting Guy! Your <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/may09\/hey0504.mspx\" target=\"_blank\">article yesterday<\/A> was fairly interesting. The problem is that every time that you looped through something, you needed to basically know how many times that you would loop because you needed to be able to count it. Also your analogy about walking on the beach was somewhat dumb. This is because to really follow alongside what you were doing in the script; you would really have to know how many times that you planned to walk on the beach during your week of vacation in Aruba. You also did not allow for what you would do if it rained. You might not have enough sense to come in out of the rain, but I bet the Scripting Wife and scripting friends do. How about giving us a better solution for looping through collections?<BR><BR>&#8211; DS<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hi DS,<\/P>\n<P>Ed here. Your e-mail message reminds me of when I was scuba diving in <A href=\"http:\/\/en.wikipedia.org\/wiki\/Maui\" target=\"_blank\">Maui, Hawaii<\/A>, in the United States several years ago. It was still dark when I headed to the beach with my dive gear. My dive buddy met me at the beach with the <A href=\"http:\/\/en.wikipedia.org\/wiki\/Diver_Propulsion_Vehicle\" target=\"_blank\">diver propulsion vehicles<\/A> (DPV). After suiting up and assembling the DPVs, we waded into the surf and headed out to the St. Anthony, a 65-feet former Louisiana Shrimp boat that was sunk as an artificial reef in 70 feet of water off Keawakapu Beach. In addition to the fun of a wreck dive, the St. Anthony is known among locals as a hangout for honu (big green sea turtles). As soon as we ditched the DPVs, we floated over to the wreck. We were in luck because there were several honu hanging out on the deck of the old ship. You can make out a few of them in this picture:<\/P><IMG border=\"0\" alt=\"Image of honu hanging out on the St. Anthony\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/may\/hey0505\/hsg-05-05-09-01.jpg\" width=\"500\" height=\"375\"> \n<P>&nbsp;<\/P>\n<P>Because I did not know how many honu there were on the wreck, I could not use the <B>For<\/B> statement. Instead, I needed to use the <B>ForEach<\/B> statement. It goes as follows:<\/P><PRE class=\"codeSample\">Foreach (honu in St. Anthony)\n{\n Take picture without approaching too close or harassing the turtle\n}\n<\/PRE>\n<TABLE id=\"ERD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">This week we continue our look at scripting with Windows PowerShell. Windows PowerShell is installed by default on Windows Server 2008 R2 and Windows 7. It is an optional installation on Windows Server 2008, and a download for <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=c6ef4735-c7de-46a2-997a-ea58fdfcba63\" target=\"_blank\">Windows Vista<\/A>, <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=6ccb7e0d-8f1d-4b97-a397-47bcc8ba3806\" target=\"_blank\">Windows XP<\/A>, and <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=10ee29af-7c3a-4057-8367-c9c1dab6e2bf\" target=\"_blank\">Windows Server 2003<\/A>. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">Windows PowerShell Scripting Hub<\/A> is a good place to start using Windows PowerShell. An excellent book for learning Windows PowerShell is the Microsoft Press book, <A href=\"http:\/\/www.microsoft.com\/MSPress\/books\/authors\/auth10329.aspx\" target=\"_blank\">Microsoft Windows PowerShell Step by Step<\/A>. This book has many hands-on labs and uses real-world examples to show the use of Windows PowerShell.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>DS, as you may have guessed by now, there is another language statement that you can use in Windows PowerShell to work your way through arrays and collections. It is called the <B>ForEach<\/B> statement, it resembles the <B>For\u2026Each\u2026Next<\/B> construction from VBScript. In the <B>DemoForEachNext.vbs<\/B> script you create an array of five numbers. They number 1 through 5. We then use the <B>For\u2026Each\u2026Next<\/B> statement to walk our way through the array that is contained in the variable <B>ary<\/B>. The variable <B>i<\/B> is used iterate through the elements of the array. The <B>For Each<\/B> block is entered as long as there is at least one item in the collection or array. When the loop is entered, all statements inside the loop are executed for the first element. In the <B>DemoForEachNext.vbs<\/B> script, this means that the following command is executed for each element in the array:<\/P><PRE class=\"codeSample\">Wscript.Echo i\n<\/PRE>\n<P>As long as there are more elements in the collection or array, the statements inside the loop continue to execute for each element. When there are no more elements in the collection or array, the loop is exited and execution continues with statement following the <B>Next<\/B> statement. This is seen in <B>DemoForEachNext.vbs<\/B>:<\/P>\n<P><B>DemoForEachNext.vbs<\/B><\/P><PRE class=\"codeSample\">ary = Array(1,2,3,4,5)\nFor Each i In ary\n  WScript.Echo i\nNext\nWscript.echo &#8220;All done&#8221;\n<\/PRE>\n<P>Why, you may ask, spend so much time talking about the <B>DemoForEachNext.vbs<\/B> script? This is because the script works exactly like the <B>DemoForEach.ps1<\/B> script. In the <B>DemoForEach.ps1<\/B> PowerShell script, you first create an array that contains the numbers 1 through 5 and store that array in the <B>$ary<\/B> variable. This is seen here:<\/P><PRE class=\"codeSample\">$ary = 1..5\n<\/PRE>\n<P>Then you use the ForEach statement to walk through the array contained in the <B>$ary<\/B> variable. Use the <B>$i<\/B> variable to keep track of your progress through the array. Inside the script block (the curly brackets) you display the value of each variable. The <B>DemoForEach.ps1<\/B> script is seen here:<\/P>\n<P><B>DemoForEach.ps1<\/B><\/P><PRE class=\"codeSample\">$ary = 1..5\nForeach ($i in $ary)\n{\n $i\n}\n<\/PRE>\n<P>The cool thing about Windows PowerShell is that you can also use the <B>ForEach<\/B> statement from inside the Windows PowerShell console:<\/P><PRE class=\"codeSample\">PS C:\\&gt; $ary = 1..5\nPS C:\\&gt; foreach($i in $ary) { $i }\n1\n2\n3\n4\n5\n<\/PRE>\n<P>The ability to use the <B>ForEach<\/B> statement from inside the Windows PowerShell console can give you excellent flexibility when you are working interactively. However, much of the work done at the Windows PowerShell console consists of using pipelining. When you are working with the pipeline, you can use the <B>ForEach-Object<\/B> cmdlet. This cmdlet behaves in a similar manner to the <B>ForEach<\/B> statement but is designed to handle pipelined input. The difference is that you do not have to use an intermediate variable to hold the contents of the array. You can create the array and send it across the pipeline. The other difference is that you do not have to create a variable for the enumerator. You use the <B>$_<\/B> automatic variable (which represents the current item on the pipeline) instead. This is seen here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; 1..5 | ForEach-Object { $_ }\n1\n2\n3\n4\n5<\/p>\n<p><\/PRE>\n<P>Suppose that you do not want to work with all the numbers in the array. This is the same thing as if one of the honu on the St. Anthony decides to head to the surface for a breath of fresh air. I could stay at the boat and continue with the next turtle or I could make a break from the ship and follow my friend. This is illustrated here:<\/P><PRE class=\"codeSample\">Foreach (honu in St. Anthony)\n{\n If (honu leaves) { Make a break from ship }\n Take picture without approaching too close or harassing the turtle\n}\n<\/PRE>\n<P>This syntax is really illustrated in this image, where the honu makes a break from the ship:<\/P><IMG border=\"0\" alt=\"Image of a honu making a break from the ship\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/may\/hey0505\/hsg-05-05-09-02.jpg\" width=\"500\" height=\"375\"> \n<P>&nbsp;<\/P>\n<P>In VBScript terms, leaving a <B>For\u2026Each\u2026Loop<\/B> early is called an <B>Exit For<\/B> statement. You have to use an <B>If<\/B> statement to perform the evaluation of the condition. When the condition is met, you call <B>Exit For<\/B>. In the <B>DemoExitFor.vbs<\/B> script you use an inline <B>If<\/B> statement to make this determination. The inline syntax is more efficient for these kinds of things than spreading the statement across three different lines. The key thing to remember about the inline <B>If<\/B> statement is it does not conclude with the final <B>End<\/B> If statement. The <B>DemoExitFor.vbs<\/B> script is seen here:<\/P>\n<P><B>DemoExitFor.vbs<\/B><\/P><PRE class=\"codeSample\">ary = Array(1,2,3,4,5)\nFor Each i In ary\n If i = 3 Then Exit For\n WScript.Echo i\nNext\nWScript.Echo &#8220;Statement following Next&#8221;\n<\/PRE>\n<P>In Windows PowerShell terms, you use the <B>break<\/B> statement to leave the loop early. Inside the script block you use an <B>If<\/B> statement to evaluate the value of the <B>$i<\/B> variable. If it is equal to 3, you call the <B>break<\/B> statement and leave the loop. This line of code is seen here:<\/P><PRE class=\"codeSample\">if($i -eq 3) { break }\n<\/PRE>\n<P>The complete <B>DemoBreakFor.ps1<\/B> script is seen here:<\/P>\n<P><B>DemoBreakFor.ps1<\/B><\/P><PRE class=\"codeSample\">$ary = 1..5\nForEach($i in $ary)\n{\n if($i -eq 3) { break }\n $i\n}\n&#8220;Statement following foreach loop&#8221;\n<\/PRE>\n<P>When the <B>DemoBreakFor.ps1<\/B> script runs, it displays the numbers 1 and 2. Then it leaves the <B>ForEach<\/B> loop and runs the line of code following the <B>ForEach<\/B> loop:<\/P><PRE class=\"codeSample\">1\n2\nStatement following foreach loop\n<\/PRE>\n<P>If you did not want to run the line of code after the loop statement, you would use the <B>Exit<\/B> statement instead of the <B>Break<\/B> statement. This is shown in the <B>DemoExitFor.ps1<\/B> script:<\/P>\n<P><B>DemoExitFor.ps1<\/B><\/P><PRE class=\"codeSample\">$ary = 1..5\nForEach($i in $ary)\n{\n if($i -eq 3) { exit }\n $i\n}\n&#8220;Statement following foreach loop&#8221;\n<\/PRE>\n<P>When the <B>DemoExitFor.ps1<\/B> script runs, the line of code following the <B>For<\/B> loop never executes. This is because the <B>Exit<\/B> statement ends the script. The results of running the <B>DemoExit script<\/B> are shown here:<\/P><PRE class=\"codeSample\">1\n2\n<\/PRE>\n<P>You could achieve the same thing in VBScript by using the <B>Wscript.Quit<\/B> statement instead of <B>Exit For<\/B>. As with the <B>DemoExitFor.ps1<\/B> script, the <B>DemoQ<\/B><B>u<\/B><B>itFor.vbs<\/B> script never comes to the line of code following the <B>For\u2026Each\u2026Loop<\/B>. This is seen here:<\/P>\n<P><B>DemoQuitFor.vbs<\/B><\/P><PRE class=\"codeSample\">ary = Array(1,2,3,4,5)\nFor Each i In ary\n If i = 3 Then WScript.Quit\n WScript.Echo i\nNext\nWScript.Echo &#8220;Statement following Next&#8221;\n<\/PRE>\n<P>DS, as you can see, you do not have to know how many items are contained within your collection in order to walk through them. In addition, even though you did not ask, we have also looked at exiting a <B>ForEach<\/B> statement when a condition is met. We hope that you have enjoyed this discussion. Join us tomorrow as we examine decision making. Until then, peace.<\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! Your article yesterday was fairly interesting. The problem is that every time that you looped through something, you needed to basically know how many times that you would loop because you needed to be able to count it. Also your analogy about walking on the beach was somewhat dumb. This is because [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,3,4,45],"class_list":["post-53823","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! Your article yesterday was fairly interesting. The problem is that every time that you looped through something, you needed to basically know how many times that you would loop because you needed to be able to count it. Also your analogy about walking on the beach was somewhat dumb. This is because [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53823","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\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=53823"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53823\/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=53823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=53823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=53823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}