February 14th, 2007

How Can I Change the Last Modified Timestamp for All the Files in a Folder?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I change the last modified timestamp for all the files in a folder? I’d like the first file to have a specified timestamp, then each subsequent file to have a timestamp one minute later than the previous file.

— AF

SpacerHey, Scripting Guy! AnswerScript Center

Hey, AF; glad to see that you’re taking a break from the 2007 Winter Scripting Games. Is that because we’re concerned that, between your regular job and the Scripting Games, you might be working too hard? Heck no; it’s because we’re concerned that we might be working too hard. At the time today’s column was being written the Scripting Games had only been running for a few hours, and we’d already received several hundred entries, each of which still has to be tested, scored, and recorded. Day 1 isn’t even half over yet, and we’re already way behind on tallying the results.

But don’t worry; after all, if anyone is used to be hopelessly behind on their commitments it’s the Scripting Guys.

At any rate, we feel like we deserve to take a little break from the Scripting Games. (Not that we’ve actually tested, scored, or recorded any of the entries yet, mind you; we got tired just counting the number of entries.) With that in mind, let’s see if we can figure out a way to change the last modified timestamp for all the files in a folder.

Well, that was easy: we can’t. Or, to be a little more specific, we can’t think of any way to carry out this task using VBScript; for better or worse, neither the FileSystemObject, the Shell Application object, nor WMI have the ability to modify file system timestamps. But if you’re willing to give Windows PowerShell a try, not only can you carry out this task, but – even better – you can do so with a minimal amount of effort:

$a = Get-Date “2/13/2007 8:00 AM”

$b = Get-ChildItem “C:\Scripts”

foreach ($i in $b) { $i.LastWriteTime = $a $a = $a.AddMinutes(1) }

$b

Explain how this all works? Well, sure we can do that (although we were hoping to get by with minimal effort ourselves). As you can see, we start out simply enough, using the Get-Date Cmdlet to create a datetime object ($a) equivalent to 8:00 AM on February 13, 2007:

$a = Get-Date “2/13/2007 8:00 AM”

As you can probably guess, we’ll use $a to represent our starting date and time.

We then use this line of code, and the Get-ChildItem Cmdlet, to retrieve a collection of all the files found in the folder C:\Scripts:

$b = Get-ChildItem “C:\Scripts”

Incidentally, AF, you noted in your email that you’d like the files to be sorted alphabetically. Turns out that was something we could do with even less than minimal effort; by default, Get-ChildItem returns its collection already sorted in alphabetical order. That means that, at the moment, we have a collection of files that looks a little something like this:

Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         2/11/2007   3:31 PM         89 1024.ps1
-a—        12/13/2006   9:11 AM         56 1026.ps1
-a—         1/21/2007   6:19 PM        133 1030.ps1
-a—          8/4/2006   4:41 PM         99 1032.ps1
-a—          2/9/2006   6:04 PM        146 1035.ps1
-a—         1/22/2005   8:05 AM         68 1045.ps1

You’re right, that was easy, wasn’t it? And guess what: changing the value of the LastWriteTime property for each file isn’t all that much harder. In fact, that’s what we do with this block of code:

foreach ($i in $b)
    {
        $i.LastWriteTime = $a
        $a = $a.AddMinutes(1)    
    }

What we’re doing here is setting up a For Each loop that loops through all the items in $b; that is, through all the files in the folder C:\Scripts:

foreach ($i in $b)

Each time we run through the loop we’re going to do two things. First, we’re going to set the LastWriteTime property of the file (represented by the variable $i) to the datetime value stored in $a:

$i.LastWriteTime = $a

That means that the first file in the collection will be assigned a LastWriteTime of 8:00 AM on February 13, 2007.

Now, if we wanted all the files in C:\Scripts to have the same timestamp we’d be done. However, that’s not what we want; instead, we want each file to have a slightly different timestamp. That’s the purpose of the second line of code inside our For Each loop:

$a = $a.AddMinutes(1)

What we’re doing here is using the AddMinutes method to increment our datetime value ($a) by 1 minute (hence the 1 that we pass to AddMinutes as the method parameter). As you no doubt recall, $a started off life being equal to 8:00 AM on February 13, 2007. By adding a minute to this value, we’re going to make $a equal to 8:01 AM on February 13, 2007. In turn, that will cause the second file in the collection to be assigned a LastWriteTime one minute later than the first file timestamp. And then the third file will be assigned a timestamp one minute later than that, the fourth file a timestamp one minute later than the third file’s, etc.

The net result? This:

Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         2/13/2007   8:00 AM         89 1024.ps1
-a—         2/13/2007   8:01 AM         56 1026.ps1
-a—         2/13/2007   8:02 AM        133 1030.ps1
-a—         2/13/2007   8:03 AM         99 1032.ps1
-a—         2/13/2007   8:04 AM        146 1035.ps1
-a—         2/13/2007   8:05 AM         68 1045.ps1

Which, all in all, seems to be just the thing you were hoping you would get.

As for the Scripting Guys, break time is over and it’s time to get to work scoring all those Scripting Games entries. Yes, sir, time to do some real work. Right … unless you have another question, AF? Oh, OK, then we guess it’s back to work. Um, unless someone else has a question. Anyone? Don’t be shy now. Anyone at all ….

Author

0 comments

Discussion are closed.