{"id":55603,"date":"2008-05-09T01:37:00","date_gmt":"2008-05-09T01:37:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/05\/09\/how-can-i-use-windows-powershell-to-report-back-the-name-and-creation-date-for-files-containing-a-specified-string-value\/"},"modified":"2008-05-09T01:37:00","modified_gmt":"2008-05-09T01:37:00","slug":"how-can-i-use-windows-powershell-to-report-back-the-name-and-creation-date-for-files-containing-a-specified-string-value","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-use-windows-powershell-to-report-back-the-name-and-creation-date-for-files-containing-a-specified-string-value\/","title":{"rendered":"How Can I Use Windows PowerShell to Report Back the Name and Creation Date for Files Containing a Specified String Value?"},"content":{"rendered":"<p><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\"> \n<P>Hey, Scripting Guy! Using Windows PowerShell, how can I search for a string value in all the files in a folder full of text files, then report back the file name and creation date for each file where that string value was found? Oh, and I\u2019d like to have these files sorted by date, too.<BR>&#8212; JS<\/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\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, JS. You know, the Scripting Guy who writes this column really misses baseball. Now, admittedly, he just wrote an entire article on that subject just <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/may08\/hey0507.mspx\"><B>yesterday<\/B><\/A>. But that was different; yesterday he missed baseball because it\u2019s possible that the Scripting Son has played his last meaningful baseball game ever. Today, however, he misses baseball for a much different, and much more important, reason: now that the season is over, the Scripting Son has decided that he and his dear old dad should go to the gym every night, run a few miles, and then lift weights for half an hour or so. (Baseball players typically don\u2019t lift weights during the season.)<\/P>\n<P>Oh. How \u2026 nice \u2026.<\/P>\n<P>In all fairness, it should be noted that the Scripting Guy who writes this column <I>does<\/I> go to the gym on a regular basis. However, while he always works up a good sweat, it tends to be a nice leisurely sweat: he rides the exercise bike or climbs the StairMaster, usually while watching Sports Center or Baseball Tonight. Does he ever run on the treadmill? No. Does he ever lift weights? No. Does he ever push himself to the brink of death? No.<\/P>\n<TABLE id=\"EHD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. Of course, when you\u2019re as old as the Scripting Guy who writes this column you\u2019re pretty much on the brink of death at all times anyway.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>In other words, the Scripting Guy who writes this column didn\u2019t exactly have a fun-filled night last night. And to add insult to injury, the Scripting Son tricked his old man. The Scripting Guy who writes this column thought the two were going to the gym to play basketball; it was only after they got there that the Scripting Son said, \u201cBy the way, we\u2019re going to run and lift weights tonight.\u201d<\/P>\n<P>Oh. How \u2026 nice \u2026.<\/P>\n<P>On the bright side, however, this <I>has<\/I> caused the Scripting Guy who writes this column to rededicate himself to his career; in fact, he has made a vow to immediately begin working harder, and to start putting in longer hours. Is that because working out makes him feel refreshed and invigorated? Well, no, not exactly; instead, he\u2019s hoping that if he stays late each night the Scripting Son will get bored and go the gym without him.<\/P>\n<P>And just to prove that he\u2019s serious about working longer and harder, the Scripting Guy who writes this column even managed to write his column today (Oh. How \u2026 nice \u2026.). Here you go, JS:<\/P><PRE class=\"codeSample\">$colFiles = Get-ChildItem C:\\Logs | Sort-Object CreationTime<\/p>\n<p>foreach ($objFile in $colFiles)\n    {\n        $strMatch = Select-String -path $objFile -pattern &#8220;Failed&#8221;\n            if ($strMatch)\n                {\n                    (Write-Host $objFile.FullName $objFile.CreationTime)\n                 }\n    }\n<\/PRE>\n<P>Before we begin we should note that we have no doubt that a true Windows PowerShell aficionado could probably dispose of this problem with a single line of code (albeit one containing multiple commands and pipelines). To tell you the truth, we were too lazy \u2013 uh, too <I>busy<\/I> to try to come up with a one-line solution to the problem. Consequently, we went with a slightly less-elegant approach, but an approach that we knew would work. If anyone out there has another, more-elegant solution feel free to <A href=\"mailto:scripter@microsoft.com\"><B>send it to us<\/B><\/A>; we\u2019d love to see what you did.<\/P>\n<P>And if you can only send that late at night, after normal working hours, that\u2019s fine; if he has to, the Scripting Guy who writes this column can stay late and wait for your email to arrive. Sure, he might miss his trip to the gym but duty calls, right?<\/P>\n<P>As for the script that <I>we<\/I> came up with, we start out by using the <B>Get-ChildItem<\/B> cmdlet to retrieve a collection of all the files in the folder C:\\Logs. As soon as we\u2019ve grabbed all the files we immediately pipe the data to the <B>Sort-Object<\/B> cmdlet, asking Sort-Object to sort all the files by their <B>CreationTime<\/B> property. We store the sorted collection in a variable named $colFiles.<\/P>\n<P>The $colFiles variable now contains a nice little collection of all the files in the folder C:\\Logs, sorted by the file creation date. That\u2019s all well and good, except for one thing: we don\u2019t want a collection of <I>all<\/I> the files in the folder C:\\Logs. Instead, we\u2019re interested only in the files that include the target string <I>Failed<\/I>. What does that mean? That means we still have some work to do.<\/P>\n<P>With that in mind, our next chore is to set up a foreach loop that allows us to loop through all the files in the collection; that\u2019s what this line of code is for:<\/P><PRE class=\"codeSample\">foreach ($objFile in $colFiles)\n<\/PRE>\n<P>Inside this loop we use the <B>Select-String<\/B> cmdlet to search the first file in the collection for the string value <I>Failed<\/I>; any instances of that value that we find in the file will be stored in the variable $strMatch:<\/P><PRE class=\"codeSample\">$strMatch = Select-String -path $objFile -pattern &#8220;Failed&#8221;\n<\/PRE>\n<P>Still with us? Good, because \u2013 believe it or not \u2013 we\u2019re almost done. How do we know whether or not this first file contains the string value <I>Failed<\/I>? That\u2019s easy; we just check to see if $strMatch has a value of some kind:<\/P><PRE class=\"codeSample\">if ($strMatch)\n<\/PRE>\n<P>What if $strMatch <I>doesn\u2019t<\/I> have a value? That\u2019s no big deal; that simply means that the first file in the collection doesn\u2019t contain the target text <I>Failed<\/I>. Consequently, we go back to the top of the loop and repeat the process with the next file in the collection.<\/P>\n<P>Of course, things are a little different if $strMatch <I>has<\/I> a value; that means that the file in question <I>does<\/I> contain the target value <I>Failed<\/I>. But, again, no big deal; in that case, we simply echo back the value of the file\u2019s <B>FullName<\/B> and CreationTime properties:<\/P><PRE class=\"codeSample\">($objFile.FullName + &#8221;       &#8221; + $objFile.CreationTime)\n<\/PRE>\n<P>From there it\u2019s back to the top of the loop, where we try again with the next file in the collection. By the time we\u2019ve finished looping through all the files in C:\\Logs we should see output similar to this onscreen:<\/P><PRE class=\"codeSample\">C:\\Scripts\\test.txt 2\/15\/2008 7:04:29 PM\nC:\\Scripts\\z.txt 3\/10\/2008 9:05:15 AM\nC:\\Scripts\\mylog.txt 4\/18\/2008 12:54:47 PM\nC:\\Scripts\\testlog.log 1 4\/18\/2008 1:03:26 PM\nC:\\Scripts\\testfile.csv 4\/18\/2008 1:06:03 PM\n<\/PRE>\n<P>Not the prettiest output in the world, but you get the idea.<\/P>\n<P>Incidentally, the one complicating factor here \u2013 at least for the Scripting Guys \u2013 was the need to echo back the file creation date along with the file name. Suppose all we cared about was the name of each file where the target text was found. In that case, this single line of code would do the trick:<\/P><PRE class=\"codeSample\">Select-String -path &#8220;C:\\Logs\\*.*&#8221; -pattern &#8220;Failed&#8221; -list | Select-Object Path\n<\/PRE>\n<P>What we\u2019re doing here is asking Select-String to look at each and every file in the folder C:\\Logs and see if it can find the word <I>Failed<\/I>. In addition, we\u2019ve tacked on the <B>\u2013list<\/B> parameter, which tells Select-String that we only want to find the first match in each file. What if we left this parameter off? Well, suppose that the file Test.txt contained 10 instances of the word <I>Failed<\/I>. In that case, we\u2019d get back 10 instances of Text.txt, one for each match.<\/P>\n<P>Oh, and if all we did was call Select-String by itself without piping it to Select-Object we\u2019d get output similar to this:<\/P><PRE class=\"codeSample\">C:\\Scripts\\mylog.txt:2:Failed\nC:\\Scripts\\test.txt:13:Failed\nC:\\Scripts\\testfile.csv:2:Failed\nC:\\Scripts\\testlog.log:2:Failed\nC:\\Scripts\\z.txt1:7:Failed\n<\/PRE>\n<P>As you can see, that\u2019s actually more information than we need; it includes not only the file <B>Path<\/B>, but also the line number where the target text was found (e.g., 2) and the target text itself. We can get rid of the line number and the target text by piping the output to <B>Select-Object<\/B>, and asking Select-Object to filter out everything except the Path property. Now our output should look like this:<\/P><PRE class=\"codeSample\">C:\\Scripts\\mylog.txt\nC:\\Scripts\\test.txt\nC:\\Scripts\\testfile.csv\nC:\\Scripts\\testlog.log\nC:\\Scripts\\z.txt\n<\/PRE>\n<P>Very nice, but, as you can see, no file creation date; that\u2019s because the Select-String cmdlet doesn\u2019t retrieve the file creation date. In turn, that\u2019s why we kicked things off by using Get-ChildItem; Get-ChildItem knows everything there is to know about file creation dates.<\/P>\n<P>We hope that answers your question, JS. Listen, as long as you\u2019re here, you don\u2019t happen to need an 18-year-old first baseman\/pitcher do you? No, no reason for asking. We were just wondering.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! Using Windows PowerShell, how can I search for a string value in all the files in a folder full of text files, then report back the file name and creation date for each file where that string value was found? Oh, and I\u2019d like to have these files sorted by date, too.&#8212; [&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":[13,3,4,14,45],"class_list":["post-55603","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-dates-and-times","tag-scripting-guy","tag-scripting-techniques","tag-text-files","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! Using Windows PowerShell, how can I search for a string value in all the files in a folder full of text files, then report back the file name and creation date for each file where that string value was found? Oh, and I\u2019d like to have these files sorted by date, too.&#8212; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55603","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=55603"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55603\/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=55603"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55603"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}