{"id":56143,"date":"2008-02-22T23:13:00","date_gmt":"2008-02-22T23:13:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/02\/22\/hey-scripting-guy-how-can-i-replace-incorrect-dates-in-my-file-names\/"},"modified":"2008-02-22T23:13:00","modified_gmt":"2008-02-22T23:13:00","slug":"hey-scripting-guy-how-can-i-replace-incorrect-dates-in-my-file-names","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-replace-incorrect-dates-in-my-file-names\/","title":{"rendered":"Hey, Scripting Guy! How Can I Replace Incorrect Dates in My File Names?"},"content":{"rendered":"<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" class=\"nearGraphic\" \/><\/p>\n<p>Hey, Scripting Guy! have a folder that has a whole bunch of files in it. Many of those files have a file name that includes an incorrect date; for example, the file might be named FGA Site Visit 2-14-<b>07<\/b> 204.jpg when it should really be named FGA Site Visit 2-14-<b>08<\/b> 204.jpg. (That is, it suggests the visit occurred in 2007 rather than 2008.) How can I replace these incorrect dates with the correct dates?<\/p>\n<p>&#8212; SM<\/p>\n<p><img decoding=\"async\" height=\"5\" width=\"5\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" alt=\"Spacer\" border=\"0\" \/><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" class=\"nearGraphic\" \/><a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><img decoding=\"async\" height=\"288\" width=\"120\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" align=\"right\" alt=\"Script Center\" border=\"0\" title=\"Script Center\" class=\"farGraphic\" \/><\/a><\/p>\n<p>Hey, SM. If you&rsquo;re a regular reader of <i>Hey, Scripting Guy!<\/i> &ndash; you know, you&rsquo;re right: that <i>is<\/i> a silly question, isn&rsquo;t it? After all, who <i>isn&rsquo;t<\/i> a regular reader of <i>Hey, Scripting Guy!<\/i>? To tell you the truth, we can&rsquo;t think of anyone. Fidel Castro? No, he writes in once or twice a month asking how to manage his DHCP server using WMI. <\/p>\n<p>And once or twice a month we tell him that there <i>is<\/i> no WMI class for managing DHCP Server. Fidel, please, stop asking about DHCP Server!<\/p>\n<p>At any rate, regular readers of this column know that <i>Hey, Scripting Guy!<\/i> typically starts off with boring personal anecdotes, meanders on through arcane references to things no one else in the world cares about, touches down once or twice on lame attempts at humor and then <i>finally<\/i> gets around to answering the question. Well, we hate to disappoint everyone, but there won&rsquo;t be any idle chitchat in today&rsquo;s column; at the moment, the Scripting Guy who writes this column has about 950 million things to do for the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/funzone\/games\/default.mspx\"><b>2008 Winter Scripting Games<\/b><\/a>, and he keeps falling farther and farther behind. So no fooling around today; we&rsquo;re just going to answer the question and then get on with it.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EBE\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\"><b>Scripting Guys trivia<\/b>. The huge backlog of Scripting Games-related tasks means that, for the first time ever, the Scripting Guy who writes this column has a bigger to-do list at work than he has at home. And he&rsquo;s had 13 years to build up that to-do list at home.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Oh, right: we <i>did<\/i> say something about just answering the question and then getting on with it, didn&rsquo;t we? Well, OK, if that&rsquo;s what we said we were going to do then that&rsquo;s what we&rsquo;re going to do:<\/p>\n<pre class=\"codeSample\">Set objRegEx = CreateObject(\"VBScript.RegExp\")<\/pre>\n<pre class=\"codeSample\">objRegEx.Global = True&nbsp;&nbsp; <br \/>objRegEx.Pattern = \"(\\d{1,2})-(\\d{1,2})-07\"<\/pre>\n<pre class=\"codeSample\">strComputer = \".\"<\/pre>\n<pre class=\"codeSample\">Set objWMIService = GetObject(\"winmgmts:\\\\\" &amp; strComputer &amp; \"\\root\\cimv2\")<\/pre>\n<pre class=\"codeSample\">Set colFileList = objWMIService.ExecQuery _<br \/>&nbsp;&nbsp;&nbsp; (\"ASSOCIATORS OF {Win32_Directory.Name='C:\\Temp'} Where \" _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp; \"ResultClass = CIM_DataFile\")<\/pre>\n<pre class=\"codeSample\">For Each objFile In colFileList<br \/>&nbsp;&nbsp;&nbsp; strOldName = objFile.Name<br \/>&nbsp;&nbsp;&nbsp; strNewName = objRegEx.Replace(strOldName,\"$1-$2-08\")<br \/>&nbsp;&nbsp;&nbsp; If strNewName &lt;&gt; strOldName Then&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; errResult = objFile.Rename(strNewName)<br \/>&nbsp;&nbsp;&nbsp; End If<br \/>Next<\/pre>\n<p>Before we launch into the details of how this script works we should note that we decided to use a regular expression to help us rename these misnamed files. At first glance that might seem like overkill; after all, couldn&rsquo;t we just search each name for the value <i>07<\/i> and replace it with the value <i>08<\/i>? Well, maybe. But, then again, maybe not. For example, suppose our folder (C:\\Temp) contains the following set of files:<\/p>\n<pre class=\"codeSample\">FGA site visit 1-14-07 204 .vbs<br \/>FGA site visit 2-14-07 205.txt<br \/>FGA site visit 2-20-07 206.txt<br \/>07 DebugMe.ps1<br \/>DebugMe-07.pl<\/pre>\n<p>As you can see, only the first three files actually contain one of our improper date values; the other two files contain the string <i>07<\/i>, but <i>not<\/i> as a date. That means that we don&rsquo;t want to replace the <i>07<\/i> in DeBugMe-07.pl; that file is <i>supposed<\/i> to be named DebugMe-07.pl, not DeBugMe-08.pl. And yet that same file <i>would<\/i> be renamed if we did a blanket search and replace for all instances of <i>07<\/i>.<\/p>\n<p>Using a regular expression helps us guard against that. With a regular expression we can &ndash; and will &ndash; search for one or two numbers followed by a hyphen, followed by one or two numbers and another hyphen, followed &ndash; at long last &ndash; by the value <i>07<\/i>. That&rsquo;s not an absolutely foolproof approach; for example, it would change the value of a file named Bob24-99-07.txt even though 24-99-07 isn&rsquo;t a date, either. <\/p>\n<p>Well, maybe in the Mayan calendar or something. But not the Gregorian calendar.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EVF\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\"><b>Note<\/b>. Was the Gregorian calendar named after Scripting Guy Greg Stemp? Oddly enough, it was actually named after Scripting Guy Jean Ross. They just misspelled <i>Jean<\/i>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>At any rate, our regular expression isn&rsquo;t foolproof. But it&rsquo;s still much safer than simply searching for and replacing any and all instances of <i>07<\/i>.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EIG\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\"><b>Note<\/b>. Yes, in theory you could create a regular expression that would be better at distinguishing dates from non-dates. But creating a regular expression like that goes way beyond what we can do in today&rsquo;s column.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>So how do we use this regular expression in our script? Well, we start out by creating an instance of the <b>VBScript.RegExp<\/b> object, the object that enables us to use regular expressions in the first place. Once we have that object in hand we then assign values to two properties of this object.<\/p>\n<p>The <b>Global<\/b> property determines whether the script searches for <i>all<\/i> instances of the target string or just the first instance. With this script it probably doesn&rsquo;t matter; however, far more often than not you <i>will<\/i> want to find all instances of the target string. Consequently, we set the value here to True.<\/p>\n<p>The <b>Pattern<\/b> represents the target text, the value we are searching for. In this case we start off by looking for at least 1, but no more than 2, digits; that&rsquo;s what this construction is for:<\/p>\n<pre class=\"codeSample\">(\\d{1,2})<\/pre>\n<p>Following the digits comes a hyphen (-) followed by 1 or 2 additional digits and yet another hyphen:<\/p>\n<pre class=\"codeSample\">(\\d{1,2})-(\\d{1,2})-<\/pre>\n<p>And then, following <i>that<\/i>, we have the hardcoded value <i>07<\/i>:<\/p>\n<pre class=\"codeSample\">(\\d{1,2})-(\\d{1,2})-07<\/pre>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EUH\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\"><b>Note<\/b>. If this syntax is making your head spin, take a look at our <a target=\"_blank\" href=\"http:\/\/www.microsoft.com\/technet\/technetmag\/issues\/2008\/01\/HeyScriptingGuy\/default.aspx\"><b>TechNet Magazine article<\/b><\/a> which introduces the use of regular expressions.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>After we configure our regular expressions object we next connect to the WMI service on the local computer. (And yes, you could run this same script against a remote computer; just assign the name of that computer to the variable strComputer.) Once the connection is made we use this crazy-looking line of code to retrieve a collection of all the files in the folder C:\\Temp:<\/p>\n<pre class=\"codeSample\">Set colFileList = objWMIService.ExecQuery _<br \/>&nbsp;&nbsp;&nbsp; (\"ASSOCIATORS OF {Win32_Directory.Name='C:\\Temp'} Where \" _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp; \"ResultClass = CIM_DataFile\")<\/pre>\n<p>At this point we&rsquo;re ready to start renaming files. To do that, we first set up a For Each loop to walk through all the files in the collection. Inside that loop, the first thing we do is retrieve the value of the file&rsquo;s <b>Name<\/b> property (the WMI equivalent of the file path), assigning that value to a variable named strOldName:<\/p>\n<pre class=\"codeSample\">strOldName = objFile.Name<\/pre>\n<p>Now it&rsquo;s time to do a little search-and-replace using our regular expression. That&rsquo;s what this line of code is for:<\/p>\n<pre class=\"codeSample\">strNewName = objRegEx.Replace(strOldName,\"$1-$2-08\")<\/pre>\n<p>Yes, this looks <i>really<\/i> crazy, but it will search the file path for the target text (two digits, a hyphen, two digits, a hyphen, and the value <i>07<\/i>). More important, it will replace the value <i>07<\/i> with the value <i>08<\/i>, all the while leaving the month and day in place. That&rsquo;s what the $1 and the $2 are for.<\/p>\n<p>We&rsquo;re glad you asked that question. $1 and $2, and $3 are examples of a regular expression &ldquo;back reference.&rdquo; A back reference is nothing more than a portion of the found text that can be saved and then reused. In this particular script we&rsquo;re looking for two &ldquo;sub-matches&rdquo;:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" class=\"listBullet\">&bull;<\/td>\n<td class=\"listItem\">\n<p>A set of 2 digits.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" class=\"listBullet\">&bull;<\/td>\n<td class=\"listItem\">\n<p>A set of 2 more digits.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Each of these sub-matches is automatically assigned a back reference: the first sub-match is $1; the second is $2; and so on, all the way through $9. In other words, suppose we have a date of 1-14-07. In that case, our regular expression would automatically assigned the following back references:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" class=\"dataTable\" id=\"EGBAC\">\n<thead><\/thead>\n<tbody>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\"><b>Date Part<\/b><\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\"><b>Back Reference<\/b><\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"evenRecord\">\n<td>\n<p class=\"lastInCell\">1<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">$1<\/p>\n<\/td>\n<\/tr>\n<tr valign=\"top\" class=\"record\">\n<td>\n<p class=\"lastInCell\">14<\/p>\n<\/td>\n<td>\n<p class=\"lastInCell\">$2<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>In our replacement string, we simply use this back references to ensure that the correct month and day are reused. Our replacement text simply says this: Take the first back reference ($1) and follow it with a hyphen. After that, insert the second back reference ($2) followed by another hyphen. Finally, tack on value <i>08<\/i>.<\/p>\n<p>What will all that give us? A file path similar to this:<\/p>\n<pre class=\"codeSample\">FGA site visit 1-14-08 204 .vbs<\/pre>\n<p>After we run the regular expression we then check to see if the new file path is the same as the old file path:<\/p>\n<pre class=\"codeSample\">If strNewName &lt;&gt; strOldName Then<\/pre>\n<p>What if the two file paths <i>are<\/i> the same? Well, that simply means that no date value could be found in the file name; that also means that there&rsquo;s no reason to rename this file. With that in mind we pop back to the top of our For Each loop and try again with the next file in the collection.<\/p>\n<p>As you might have guessed, if the paths <i>are<\/i> different that means that the file needs to be renamed. That&rsquo;s something we can do using this one line of code and the <b>Rename<\/b> method:<\/p>\n<pre class=\"codeSample\">errResult = objFile.Rename(strNewName)<\/pre>\n<p>And then it&rsquo;s back to the top of the loop, where we repeat the process with the next file in the collection.<\/p>\n<p>When all is said and done our folder should now contain the following files:<\/p>\n<pre class=\"codeSample\">FGA site visit 1-14-08 204 .vbs<br \/>FGA site visit 2-14-08 205.txt<br \/>FGA site visit 2-20-08 206.txt<br \/>07 DebugMe.ps1<br \/>DebugMe-07.pl<\/pre>\n<p>Nice.<\/p>\n<p>That should do it, SM; if it doesn&rsquo;t let us know. (Although if you could wait a week or two, until the Scripting Games are over, that would really help.) As for all you Scripting Games competitors who keep writing in asking why your scores haven&rsquo;t been updated, well, we&rsquo;re working on it. We hope to be sort of caught up by Monday, but we can&rsquo;t make any promises. Just be patient.<\/p>\n<p>Which reminds us of a long, pointless, and not-all-that-amusing story, the very thing that the Scripting Guy who writes this column specializes in. As it turns out, the other day the Scripting Son was looking for his baseball glove, and he &ndash; well, OK, good point: maybe we <i>should<\/i> try getting caught up on our Scripting Games duties and <i>then<\/i> tell our long and pointless story. Once we get caught up just remind us about the story, OK? Thanks.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! have a folder that has a whole bunch of files in it. Many of those files have a file name that includes an incorrect date; for example, the file might be named FGA Site Visit 2-14-07 204.jpg when it should really be named FGA Site Visit 2-14-08 204.jpg. (That is, it suggests [&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,174,3,4,5],"class_list":["post-56143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-regular-expressions","tag-scripting-guy","tag-scripting-techniques","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! have a folder that has a whole bunch of files in it. Many of those files have a file name that includes an incorrect date; for example, the file might be named FGA Site Visit 2-14-07 204.jpg when it should really be named FGA Site Visit 2-14-08 204.jpg. (That is, it suggests [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/56143","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=56143"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/56143\/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=56143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=56143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=56143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}