Hey, Scripting Guy! Question

Hey, Scripting Guy! I'm looking for a script that can search a file server and list the number and total size of files that have been recently modified or added to the server. Any help would be appreciated!

-- KT

SpacerHey, Scripting Guy! AnswerScript Center

Hey, KT. Before we launch into today’s column we thought we should tell you that the rumor is true: Scripting Guy Dean Tsaltas is actually a real, live Sasquatch, the fabled “Bigfoot” monster of the Pacific Northwest. Dean has been trying to keep his true identity a secret for many years, but – oh, we see: you meant the other rumor. Well, the other rumor happens to be true, too: the special edition Winter Scripting Games bobbleheads have arrived, and are ready to be mailed out to 250 lucky winners.

Note. That thing about Dean being a real, live Sasquatch? That was just … a mistake …. Yeah, a mistake: Dean just doesn’t shave as often as he should. But just because he doesn’t shave very often that doesn’t make him a Sasquatch. And neither does the fact that he is 11-feet 2-inches tall with long arms, an ape-like face with a flat nose, and thick hairy fur. Doesn’t make him a Sasquatch at all.

Anyway, the bobbleheads have arrived, which actually took us by surprise: after all, they weren’t due until the middle of March.

Note. OK, granted, it is the middle of March. But last year the bobbleheads were supposed to arrive in the middle of February, and we didn’t get them until April. As a result, we weren’t ready for 14 huge boxes of bobbleheads to arrive. If you could see Scripting Guy Greg Stemp’s office right now we would be amazed, because you can barely even get in Scripting Guy Greg Stemp’s office right now.

All of that means we can now go ahead and draw names and pick the winners of the bobbleheads, along with the winners of all the other great prizes being given away as part of the 2008 Winter Scripting Games. Sometime today we’ll start sending out emails notifying people of what they have won, if anything. But be patient: between the bobbleheads, the Certificates of Excellence, and all the other prizes we have hundreds of emails to send out. That will likely take us a few days.

And, unfortunately, Dean won’t be able to help us with those emails. He called earlier today and said he would be stuck on the Collings Mountain Trail in southern Oregon for awhile. And no, he didn’t say why.

So what are you supposed to do while you wait to hear if you won a Scripting Games prize? Nothing; you should simply stare at your email inbox and wait until a message from the Scripting Guys arrives (assuming you’ve won something; if not no message will arrive and, well, you could be staring at your inbox for a while).

Or, if you find that a bit too boring, you could read the rest of this column, and find out how to get the total number (and total size) of all the files created or modified on a computer since a specified date.

And no, we have no suggestions as to what you can do if you find this column a bit too boring, too. At that point, you’re on your own.

Let’s start by taking a look at a script that returns a collection of all the files that have been added to a computer since March 12, 2008:

strMonth = "03"
strDay = "12"
strYear = "2008"

strDate = strYear & strMonth & strDay & "000000.000000+000"

intNumberOfFiles = 0
intTotalSize = 0

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colFiles = objWMIService.ExecQuery _
    ("Select * From CIM_DataFile Where CreationDate >= '" & strDate & "'")

For Each objFile in colFiles
    intNumberOfFiles = intNumberOfFiles + 1
    intTotalSize = intTotalSize + objFile.FileSize
Next

Wscript.Echo "Total files added: " & intNumberOfFiles
Wscript.Echo "Total size of the new files: " & intTotalSize

As it turns out, it’s fairly easy – though a bit time-consuming – to retrieve a collection of all the files found on all the drives of a computer; that’s because each file is a member of the WMI class CIM_DataFile. The tricky part is working with the creation and last modified dates of these files; that’s because WMI uses the Universal Time Coordinate (UTC) format for storing date-time values. What does that mean? That means that a date like March 12, 2008 looks like this:

20080312000000.000000+000

Believe it or not, there is method to that madness. The 2008 at the beginning of the string represents the year; the 03 represents the month (note the leading zero); and the 12 represents the day. (For more information on the UTC format, see the Microsoft Windows 2000 Scripting Guide.) What we need to do before we do anything else is take a date like March 12, 2008 and convert it to UTC format.

Which is exactly what we do with this block of code:

strMonth = "03"
strDay = "12"
strYear = "2008"

strDate = strYear & strMonth & strDay & "000000.000000+000"

All we’re doing here is assigning the month, day, and year to the variables strMonth, strDay, and strYear. (Note, again, the leading zeroes that must be used for any month or day less than 10. Also note that the year must include four digits.) Once we’ve done that we then use this line of code to combine these values and assign the resulting string to a variable named strDate:

strDate = strYear & strMonth & strDay & "000000.000000+000"

And what will strDate be equal to? You got it:

20080312000000.000000+000

As soon as we’ve taken care of the date the rest is easy. To begin with, we assign the value 0 to the variables intNumberOfFiles and intTotalSize; we’ll talk about these two variables in a few minutes. From there we proceed to connect to the WMI service on the local computer. Can we run this script against a remote computer? Of course we can; all we have to do is assign the name of that remote machine to the variable strComputer:

strComputer = "atl-fs-001"

After connecting to the WMI service we use this line of code to return a collection of all the files on the computer that have a CreationDate greater than or equal to the variable strDate:

Set colFiles = objWMIService.ExecQuery _
    ("Select * From CIM_DataFile Where CreationDate >= '" & strDate & "'")

Keep in mind that, by default, WMI is going to search your entire computer (that is, each and every drive) and track down each and every file with the specified CreationDate. What does that mean? That means that, depending on the size of your disk drives and depending on the number of files found on your computer, this script could (and no doubt will) take several minutes to complete.

Note. Can you speed things up at all? No, not if you need to find all the files on all the drives. If you’re interested in the files found on only a particular drive, however, you could add a Where clause limiting the returned data to that drive. For example, this query searches for new files only on drive D:

("Select * From CIM_DataFile Where CreationDate >= '" & strDate & "' AND Drive = 'D:'")

Sooner or later, the script will complete. (Again, you might have to be patient here.) When it does, we’ll have a collection of all the files on the computer that have the specified CreationDate. So how do we determine the number, and the total size, of those files? Here’s one way:

For Each objFile in colFiles
    intNumberOfFiles = intNumberOfFiles + 1
    intTotalSize = intTotalSize + objFile.FileSize
Next

What we’ve done here is set up a For Each loop to loop through each of the files in our collection. For each of those files, we do two things. First, we increment the value of intNumberOfFiles by 1. As you might have guessed, we’ll use this variable to keep track of the number of files found in the collection. And yes, alternatively, we could have simply echoed back the value of the collection’s Count property; that will also tell us the number f files that were found. However, we decided to count the files one-by-one simply because we had to use a For Each loop to loop through the collection anyway.

Why did we need to use a For Each loop to loop through the collection? Because the only way we can determine the total size of all the new files is to add the size of each individual file. That’s what we do in this line of code, where we take the value of the file’s FileSize property and add it to the variable intTotalSize:

intTotalSize = intTotalSize + objFile.FileSize

And then it’s back to the top of the loop, where we repeat this process with the next file in the collection. Once we’ve finished looping through the set of files we echo back the value of the variables intNumberOfFiles and intTotalSize:

Wscript.Echo "Total files added: " & intNumberOfFiles
Wscript.Echo "Total size of the new files: " & intTotalSize

That, in turn, should result in output similar to this:

Total files added: 42
Total size of the new files: 69559

Again, this is not the fastest script in the world (not even close), but it is thorough. And it will bring back the information you’re looking for.

That takes care of new files that have been added to the computer; now, what about files that have been modified since March 12, 2008? To add that capability, tack this code on to the bottom of the script:

intModifiedFiles = 0
intModifiedSize = 0

Set colFiles = objWMIService.ExecQuery _
    ("Select * From CIM_DataFile Where LastModified >= '" & strDate & "'")

For Each objFile in colFiles
    intModifiedFiles = intModifiedFiles + 1
    intModifiedSize = intModifiedSize + objFile.FileSize
Next

Wscript.Echo "Total files modified: " & (intModifiedFiles – intNumberOfFiles)
Wscript.Echo "Total size of the modified files: " & (intModifiedSize – intTotalSize)

As you can see, this is quite similar to the code for finding new files. For starters, we assign the value 0 to two new variables, intModifiedFiles and intModifiedSize. We then use this line of code to retrieve a collection of all the files where the value of the LastModified property is greater than or equal to strDate:

Set colFiles = objWMIService.ExecQuery _
    ("Select * From CIM_DataFile Where LastModified >= '" & strDate & "'")

After we’ve done that, we set up a For Each loop to calculate the total number of files (intModifiedFiles) and the total size of those files (intModifiedSize). That brings us to these two lines of code:

Wscript.Echo "Total files modified: " & (intModifiedFiles – intNumberOfFiles)
Wscript.Echo "Total size of the modified files: " & (intModifiedSize – intTotalSize)

Here we’re echoing back the number and size of the all the files that have been modified since March 12, 2008. Notice, however, that we aren’t simply echoing back the value of intModifiedFiles in order to determine the total number of files; instead, we’re echoing back the value of intModifiedFiles minus intNumberOfFiles:

(intModifiedFiles – intNumberOfFiles)

Why do we do that? Well, as it turns out, a file that is created on March 12, 2008 doesn’t just get a creation date of March 12, 2008; it also gets a last-modified date of March 12, 2008. That means this one file will get counted twice: it gets counted as a new file and as a modified file. In order to guard against this, we subtract the new files from the modified files. For example, suppose we find 10 new files and 25 modified files. Those 25 modified files will include the new files. To get a more accurate count of the modified files, we subtract the 10 new files from the 25 modified files.

From there we do the same thing for the file size. And then that, as they say, is that.

Really.

That should do it, KT; let us know if you have any problems. Oh, and while you’re at it, please let us know if you see Dean anywhere; we’re starting to get a little worried about him. Thank you for your help.