{"id":55593,"date":"2008-05-10T01:38:00","date_gmt":"2008-05-10T01:38:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/05\/10\/hey-scripting-guy-how-can-i-use-windows-powershell-to-pick-out-the-unique-file-extensions-used-in-a-collection-of-files\/"},"modified":"2008-05-10T01:38:00","modified_gmt":"2008-05-10T01:38:00","slug":"hey-scripting-guy-how-can-i-use-windows-powershell-to-pick-out-the-unique-file-extensions-used-in-a-collection-of-files","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-use-windows-powershell-to-pick-out-the-unique-file-extensions-used-in-a-collection-of-files\/","title":{"rendered":"Hey, Scripting Guy! How Can I Use Windows PowerShell to Pick Out the Unique File Extensions Used in a Collection of Files?"},"content":{"rendered":"<p><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/> <\/p>\n<p>Hey, Scripting Guy! I\u2019m having a strange problem with Windows PowerShell, and I was wondering if you could help me solve it. I\u2019m trying to get a list of the unique file extensions used by the files in a folder. I have a whole bunch of different file types in that folder, but every time I run my command it returns just one file extension. What am I doing wrong?<br \/>&#8212; TH<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\" \/><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/><a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><img decoding=\"async\" class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\" \/><\/a> <\/p>\n<p>Hey, TH. You know, this has been a difficult morning for the Scripting Guy who writes this column. To get from the Scripting House to the office, this Scripting Guy has to drive through town, and make his way through 25 or so traffic lights. (Why doesn\u2019t he just take the freeway? That\u2019s easy: because he lives in the Seattle area. To paraphrase Yogi Berra, \u201cNo one takes the freeway any more; it\u2019s too crowded.\u201d)<\/p>\n<p>This morning, in what surely ranks as one of the greatest driving feats in recorded history, the Scripting Guy who writes this column made it through the first 22 traffic lights <i>without stopping<\/i>. Seventy-one years after his flight Charles Lindbergh is still celebrated for being the first person to fly an airplane nonstop across the Atlantic. Trust us, that\u2019s <i>nothing<\/i> compared to being the first person to drive a car nonstop from Kirkland to Redmond. With just a few blocks left to go the Scripting Guy who writes this column was already trying to decide which baseball hat he would wear during the tickertape parade that would no doubt be held in his honor.<\/p>\n<table class=\"dataTable\" id=\"ECD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. In case you\u2019re wondering, he decided to wear the same ratty old hat he\u2019s worn every day for the last four years. As it turns out, it wasn\u2019t that difficult of a decision to make after all.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Unfortunately, though, things were simply not to be: three traffic lights away from immortality, the light turned red and the Scripting Guy who writes this column was forced to stop. Ironically, the light that stopped his push towards fame and fortune just happened to be the first traffic light you encounter after reaching Microsoft.<\/p>\n<table class=\"dataTable\" id=\"EOD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note<\/b>. Is that some sort of metaphor for the life of the Scripting Guys, the fact that, just when everything seemed to be going great Microsoft up and puts a stop to it? To tell you the truth, we better not answer that question.<\/p>\n<p>But in answer to your question, yes it <i>is<\/i> a metaphor for the life of the Scripting Guys.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>As TH has discovered, stoplights aren\u2019t limited to roads and highways; sometimes you encounter a red light in Windows PowerShell as well. TH has a command that looks like this:<\/p>\n<pre class=\"codeSample\">Get-ChildItem C:\\Scripts | Select-Object Extension | Sort-Object Extension | Get-Unique\n<\/pre>\n<p>This command kicks off by using the <b>Get-ChildItem<\/b> cmdlet to return a collection of all the files in the folder C:\\Scripts. Because TH is interested in only file extensions, he pipes that collection to the <b>Select-Object<\/b> cmdlet, asking Select-Object to weed out everything except the <b>Extension<\/b> property. That collection is then piped to the <b>Sort-Object<\/b> cmdlet, which sorts all the file extensions. Finally, TH uses the <b>Get-Unique<\/b> cmdlet to echo back a single instance of each file extension found in C:\\Scripts.<\/p>\n<p>Make sense? In other words, suppose C:\\Scripts has the following set of files:<\/p>\n<pre class=\"codeSample\">Test1.doc\nTest2.doc\nTest3.mdb\nTest4.ppt\nTest5.ppt\nTest6.ppt\nTest7.xls\nTest8.xls\n<\/pre>\n<p>This set of 8 files uses 4 different file extensions: .doc; .mdb; .ppt; and .xls. Because of that, TH assumes he\u2019ll get back the following report:<\/p>\n<pre class=\"codeSample\">.doc\n.mdb\n.ppt\n.xls\n<\/pre>\n<p>Instead, he gets back this:<\/p>\n<pre class=\"codeSample\">.doc\n<\/pre>\n<p>Obviously something went wrong. But what?<\/p>\n<table class=\"dataTable\" id=\"EYE\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note<\/b>. First, however, let\u2019s relate the only traffic light joke that the Scripting Guy who writes this column knows:<\/p>\n<p>\u201cWhat did the first stoplight say to the second stoplight?\u201d<\/p>\n<p>\u201cDon\u2019t look at me; I\u2019m changing!\u201d<\/p>\n<p>And yes, it\u2019s probably for the best that this is the only traffic light joke that he knows.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>In order to explain the problem TH has run into it helps to know what the Get-Unique cmdlet does. Suppose we have an array like the following:<\/p>\n<pre class=\"codeSample\">$a = 5,2,3,2,6,6,2,9,2,2,2,3,5,5,2,2,2,5,4,4,4,3,3,2,2,6,4,4,5,6,2,2,7,2,6,6,3\n<\/pre>\n<p>Now, suppose we need to know how many unique numerals are used in that array. How can we determine the unique numerals used in the array? That\u2019s easy: we first sort the array, then pass the sorted list to Get-Unique:<\/p>\n<pre class=\"codeSample\">$a | Sort-Object | Get-Unique\n<\/pre>\n<p>In turn, Get-Unique reports back the following:<\/p>\n<pre class=\"codeSample\">2\n3\n4\n5\n6\n7\n9\n<\/pre>\n<p>Pretty cool, huh?<\/p>\n<p>What\u2019s that, you say? Isn\u2019t that the exact same thing that TH did? Well, almost, but not quite; there\u2019s one important difference. At the start of his command, TH used Get-ChildItem to return a collection of all the files found in the folder C:\\Scripts; Get-ChildItem is going to bring back a collection of <i>objects<\/i>, with each object representing a file found in C:\\Scripts. (By contrast, there are no objects in our array, just numeric values.) TH then passes those objects to Select-Object and Sort-Object. When that\u2019s done he still has a collection of objects. Admittedly, there\u2019s not a whole lot left of these objects; in fact, what he has are a bunch of file objects that contain a single property: Extension. Nevertheless, these <i>are<\/i> still objects. <\/p>\n<p>And that\u2019s why TH\u2019s command <i>seems<\/i> to fail. (As it turns out, it\u2019s actually doing what it\u2019s supposed to.) TH handed Get-Unique a collection of objects, each object containing a single property. He then asked Get-Unique to report back the unique items in that collection. As it turns out, all the items are identical: they\u2019re all file objects with a single property. Consequently, Get-Unique correctly reports back a single instance of the file object:<\/p>\n<pre class=\"codeSample\">.doc\n<\/pre>\n<table class=\"dataTable\" id=\"E2F\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. Yes, we know: intuitively that doesn\u2019t make much sense. But think about it for a bit; after awhile you\u2019ll understand why it works that way.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>So how do we solve TH\u2019s problem? That\u2019s easy; we just need to add Get-Unique\u2019s <b>\u2013asString<\/b> parameter:<\/p>\n<pre class=\"codeSample\">Get-ChildItem C:\\Scripts | Select-Object Extension | Sort-Object Extension | Get-Unique -asString\n<\/pre>\n<p>The \u2013asString parameter tells Get-Unique to work with property values rather than objects; because of that, Get-Unique will look at the actual value of each property in the object rather than looking solely at the object type. In turn, that means that Get-Unique will correctly report back the unique file extensions:<\/p>\n<pre class=\"codeSample\">.doc\n.mdb\n.ppt\n.xls\n<\/pre>\n<p>Much better.<\/p>\n<p>Incidentally, suppose you wanted to know which file extensions were <i>trul<\/i>y unique; that is, which file extensions are used one time and one time only. As far as we know there\u2019s no way to do that using Get-Unique. However, you <i>can<\/i> do that using a command similar to this one:<\/p>\n<pre class=\"codeSample\">Get-ChildItem C:\\Scripts | Group-Object Extension | Where-Object {$_.Count -eq 1} | Select-Object Name\n<\/pre>\n<p>To explain how this command works let\u2019s go back to the array $a and use a similar command to retrieve the truly unique, one-of-kind items from $a:<\/p>\n<pre class=\"codeSample\">$a | Group-Object | Where-Object {$_.Count -eq 1} | Select-Object Name\n<\/pre>\n<p>As you can see, here we take the variable $a and pipe it to the Group-Object cmdlet; in turn, Group-Object will categorize all the items in the array, like so:<\/p>\n<pre class=\"codeSample\">Count Name                      Group\n----- ----                      -----\n    5 5                         {5, 5, 5, 5...}\n   14 2                         {2, 2, 2, 2...}\n    5 3                         {3, 3, 3, 3...}\n    6 6                         {6, 6, 6, 6...}\n    1 9                         {9}\n    5 4                         {4, 4, 4, 4...}\n    1 7                         {7}\n<\/pre>\n<p>The <b>Count<\/b> property indicates the number of items in each group; if a group has a Count of 1 that means there\u2019s only one item in that group. In order to grab those particular groups we pipe the data to the <b>Where-Object<\/b> cmdlet and ask Where-Object to pick out those groups where the Count is equal to 1:<\/p>\n<pre class=\"codeSample\">Where-Object {$_.Count -eq 1}\n<\/pre>\n<p>Finally, we use Select-Object to report back the value of the <b>Name<\/b> property:<\/p>\n<pre class=\"codeSample\">Select-Object Name\n<\/pre>\n<p>That should result in the following information being echoed back to the screen:<\/p>\n<pre class=\"codeSample\">Name\n----\n9\n7\n<\/pre>\n<p>If you go back to line of code where we assigned values to the array you should find just one instance of the number 9 and one instance of the number 7.<\/p>\n<p>That should take care of things, TH; let us know if it doesn\u2019t. We should also note that while the Scripting Guy who writes this column would have been proud to be the first person to drive nonstop from Kirkland to Redmond, passing through 25 consecutive traffic lights would not have been a world\u2019s record; heck, it wouldn\u2019t have even been a <i>family<\/i> record. <\/p>\n<p>Which must mean it\u2019s time for another amusing family story. When the Scripting Guy who writes this column was a kid the Scripting Family took a trip to southern California, passing through San Francisco on the way. <\/p>\n<table class=\"dataTable\" id=\"EUH\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. And no, the family did <i>not<\/i> travel by covered wagon; the Scripting Guy who writes this column isn\u2019t <i>that<\/i> old. Instead, the family took one of those new-fangled horseless carriages.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>As it turns out, the Scripting Dad was following a family friend through town, and this family friend had the disconcerting habit of driving through yellow lights. The Scripting Dad didn\u2019t want to get lost, so he dutifully kept pace, something which caused him to run 28 consecutive <i>red<\/i> lights. <i>That\u2019s<\/i> a record that will never be broken.<\/p>\n<p>Well, at least not by anyone likely to live to tell the tale.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I\u2019m having a strange problem with Windows PowerShell, and I was wondering if you could help me solve it. I\u2019m trying to get a list of the unique file extensions used by the files in a folder. I have a whole bunch of different file types in that folder, but every time [&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":[38,3,12,45],"class_list":["post-55593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-scripting-guy","tag-storage","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I\u2019m having a strange problem with Windows PowerShell, and I was wondering if you could help me solve it. I\u2019m trying to get a list of the unique file extensions used by the files in a folder. I have a whole bunch of different file types in that folder, but every time [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55593","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=55593"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55593\/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=55593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}