Files and Folders, Part 1

By The Microsoft Scripting Guys

Sesame Script

Welcome to Sesame Script, the column for beginning script writers. The goal of this column is to teach the very basics of Windows scripting for system administration automation. We’ll provide you with the information you’ll need to begin reading and understanding scripts and to start modifying those scripts to suit your own needs. If there’s anything in particular about scripting you’re finding confusing, let us know; you’re probably not alone.

Check the Sesame Script Archives to see past articles.

On This Page

The Many Faces of Files and Folders
Check for Files and Folders
Copy Files and Folders
Move Files and Folders
Delete Files and Folders
Copy by Date
It’s All Yours

The Many Faces of Files and Folders

We’ll be honest with you, because the Scripting Guys are generally honest people (not always to their benefit): the Scripting Guys are tired. Now, we could explain why we’re tired, but every once in awhile we actually know when being honest isn’t going to be to our benefit, and this just happens to be one of those times. Not only would it not be to our benefit, but if you’re interested in ever hearing from us again, well, then it wouldn’t be to your benefit either.

So with that, and being as tired as we are, we’ve decided to go beyond the usual Sesame Script and get into a topic so big it will take two articles to cover, maybe even three. (And if that didn’t make any sense to you, well, are you really surprised?)

In our last Sesame Script we talked about shrimp. We’re not going to do that this time. This time we’re going to talk about subrogation. We’re going to talk about subrogation because it’s such a cool word and the Scripting Guys actually had to look it up to find out what it means. We’ll save you the trouble and tell you that subrogation is where you end up after you’ve gone on a business trip and come back with staples in your head.

All right, that’s not entirely true. Subrogation doesn’t actually start until your insurance company gets the hospital bill.

That leads us directly into our topic for this month: Files and Folders. Oh, and dates. (See, there was a reason for the shrimp discussion last month: we were setting you up for the subrogation discussion this month.)

Unlike subrogation, the topic of files and folders seems to be pretty popular, at least based on the email we receive. (Fortunately we receive very little email on subrogation, although the email we did get required a certain Scripting Guy to fill out some forms and answer a lot of questions.) A lot of the file and folder questions we get revolve around moving files, so that’s mostly what we’re going to talk about.

You might be wondering why in the world it would take two (or three) articles to talk about moving files around. The reason is because there’s more than one way to do this; for example, there’s the FileSystemObject and there’s Windows Management Instrumentation (WMI). Oh, and there’s Windows PowerShell to boot. If there’s a third article it will be the Windows PowerShell one, but we haven’t decided on that yet; we’ll get back to you in a couple of months. In the meantime, let us know if that’s something you’d like to read about here in Sesame Script.

There are advantages and disadvantages to using each of the two methods we’re going to be talking about (we’re ignoring option 3 for now). Here are a couple examples:

  • WMI can be used to access files and folders on remote computers; FileSystemObject only works locally (for the most part).

  • The FileSystemObject is a little bit easier to work with, especially when it comes to dates.

You can get a more detailed discussion of the differences between the two in the Microsoft Windows 2000 Scripting Guide.

In this part, which you’ve probably figured out is Part 1, we’re going to talk about working with files and folders using the FileSystemObject.

Check for Files and Folders

Question 1: Please identify all injuries and/or conditions sustained.

Don’t worry folks, just part of the subrogation process. This discussion really should be pretty painless.

We’re going to start this discussion by assuming that the injury has already occurred - or, more accurately, that the files we’re going to be working with already exist. If that’s not the case, well, then you shouldn’t be in subrogation.

All right, we won’t make that assumption. Instead we’re going to check whether the files and folders we’re going to work with exist:

Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists("C:\scripts") Then
    If objFSO.FileExists("C:\scripts\test.txt") Then
        Wscript.Echo "Folder and file exist"
    Else
        Wscript.Echo "Folder exists, file doesn't"
    End If
Else
    Wscript.Echo "Folder does not exist"
End If

The first thing we do in this script is use the CreateObject method to create an instance of the Scripting.FileSystemObject:

Set objFSO = CreateObject("Scripting.FileSystemObject")

Next we enter an If statement. This If statement is a little tricky because it’s a nested If - an If statement within an If statement. What we want to do is check to see if a specific folder exists. If it does, we then want to check for a specific file within that folder. We then echo a message giving us the results. We start by checking to see if the folder exists. We do this by calling the FolderExists method of the FileSystemObject:

If objFSO.FolderExists("C:\scripts") Then

Here we’re checking for the folder C:\scripts, which we’ve passed as a parameter to the FolderExists method. FolderExists returns True if the folder exists and False if it doesn’t, so we’re able to put the method call right into the If statement. If the folder exists, and FolderExists returns True, we move on to the next If statement:

If objFSO.FileExists("C:\scripts\test.txt") Then

This time, rather than checking to see if a folder exists, we’re checking to see if a file exists; therefore, we pass the name of the file to the FileExists method. (Note that, if we wanted to check for a file in the current directory, we don’t have to pass the full file path, we can simply pass the file name.) FileExists returns True if the specified file exists and False if it doesn’t, so, just like with the FolderExists method, we’re able to put the method call right into the If statement. If FileExists returns True, meaning the file does exist, we echo a message stating that the folder and the file both exist:

Wscript.Echo "Folder and file exist"

We already know that the folder exists, so if FileExists returns False we fall into the Else statement and echo the message that the folder exists but the file doesn’t:

Else
    Wscript.Echo "Folder exists, file doesn't"

Finally, if we never even made it to the second If statement (because FolderExists returned False) we fall into the outer Else statement and echo the message that the folder doesn’t exist:

Else
    Wscript.Echo "Folder does not exist"

Copy Files and Folders

Question 2: Did the injury occur in, on or near a motor vehicle?

No, the children were safely off the school bus when the grizzly attacked.

Now that we know we have a file, let’s take a look at moving that file somewhere. The first thing we’re going to do is copy the file from one folder to another. Here’s a script that copies Test.txt from C:\scipts to C:\scripts\temp:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

objFile.Copy "C:\scripts\temp\"

Not much to it, is there? We first create a reference to the FileSystemObject, then retrieve a reference to the file we want to copy; we do that by calling the GetFile method. We pass one parameter to GetFile, which, conveniently enough. happens to be the path to the file we want to copy:

Set objFile = objFSO.GetFile("C:\scripts\test.txt")

Finally, we call the Copy method on the File object, passing it the path to the location where we want to copy the file:

objFile.Copy "C:\scripts\temp\"

Incidentally, the Copy method does accept on more parameter. This parameter specifies whether or not you want to overwrite the file if a file by the same name already exists in the destination folder. The default is True, meaning the file will be overwritten. If you don’t want existing files to be overwritten, pass False as the second parameter to the Copy method:

objFile.Copy "C:\scripts\temp\", False

You can also use the Copy method to copy the entire contents of one folder to another:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\scripts")

objFolder.Copy "C:\temp"

There’s not much difference between this script and the last one we just saw. Once again we create a reference to the FileSystemObject, but this time, rather than calling the GetFile method, we call the GetFolder method, passing the path to the folder whose contents we want to copy:

Set objFolder = objFSO.GetFolder("C:\scripts")

We now have an object reference to that folder, and we use that object to call the Copy method:

objFolder.Copy "C:\temp"

This copies all the files and folders from the C:\scripts folder, including all the files and folders within all the subfolders, into the C:\temp folder. Notice a couple of difference between the path we passed to the folder copy (C:\temp) and the path we passed to the file copy (C:\scripts\temp\). For starters, in the folder copy we don’t end the path with the backslash (\). We also don’t specify a subfolder of the folder we’re trying to copy. That would basically be like trying to recursively copy a file into itself, and it would just confuse everything.

As with the file copy, we can also pass a second parameter to the folder copy indicating whether we want to overwrite existing files and folders:

objFolder.Copy "C:\temp", False

A value of False means “Don’t overwrite existing files and folders.” (The default is True).

We can also copy files and folders without having to first connect to the file or folder object. In addition to the Copy method, the FileSystemObject provides two other methods for copying files and folders: CopyFile and CopyFolder. Let’s take a look at CopyFile first:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.CopyFile "C:\scripts\test.txt","C:\scripts\temp\"

Yes, that’s really all there is to it. You simply create a reference to a FileSystemObject, then call the CopyFile method. As you can see, we pass two parameters to CopyFile: the file we’re copying (C:\scripts\test.txt) and the location we’re copying the file to (C:\scripts\temp\). After running this script, the file test.txt will still exist in C:\scripts, but now there will also be a copy of that file (named test.txt) in C:\scripts\temp. (Keep in mind that both the source file and the destination folder must already exist or you’ll receive an error.)

Just like the Copy method, CopyFile accepts an additional parameter that allows you to specify whether or not the script should overwrite an existing file. If you set the second parameter to False and the file you’re trying to copy already exists in the specified location, you’ll receive this error when you run the script:

C:\scripts\test.vbs(2, 1) Microsoft VBScript runtime error: File already exists

The CopyFolder method works pretty much the same way:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.CopyFolder "C:\scripts","C:\scriptstest"

Once again we start by creating a FileSystemObject. We then call CopyFolder, passing it two parameters: the folder we want to copy (C:\scripts) and the folder we want to copy to (C:\scriptstest). CopyFolder copies all the files and folders from the source folder to the new destination folder, including all files and folders within any subfolders. If the folder we specify as the destination doesn’t exist, CopyFolder will create that folder.

Just like CopyFile, CopyFolder also has a third parameter that accepts True or False, True meaning overwrite the folder if it exists (the default), or False meaning don’t overwrite. If you’re wondering why you’d use Copy versus CopyFile or CopyFolder, CopyFile and CopyFolder have an additional capability that Copy doesn’t. The Copy method copies only one file or folder at a time; CopyFile and CopyFolder can copy multiple files and folders:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.CopyFile "C:\scripts\*.txt","C:\scripts\temp\"

Notice the first parameter we passed to CopyFile: C:\scripts\*.txt. Instead of passing a specific file name, we used the * wildcard character to say “all the files in the C:\scripts folder that end with .txt.” After running this script, all .txt files in C:\scripts will have been copied to C:\scripts\temp.The same thing can be done with folders:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.CopyFolder "C:\s*","C:\temp"

When we called CopyFolder earlier, with the full name of a folder, the entire contents of that folder were copied to the destination. In this case, we’ve used a wildcard to say we want to copy all the folders off the C: drive that start with the letter s. (And we’ve specified C:\temp as the destination.) But rather than just taking the contents of each folder beginning with the letter s and copying those contents into C:\temp, CopyFolder will copy the entire folder itself. For example, if you have a folder named C:\scripts with two files in it, Test.txt and Test2.txt, after running the preceding script your C:\temp folder will look like this:

C:\temp
    C:\temp\scripts
        C:\temp\scripts\Test.txt
        C:\temp\scripts\Test2.txt

When you think about it this makes a lot of sense. If only the contents of multiple files were copied over, you’d end up with a large mishmash of unorganized files in your C:\temp folder. And who wants a large mishmash full of unorganized files?

Move Files and Folders

Question 3: Was this injury/condition sustained while performing work required for employment?

Depends on what you consider work…do the Scripting Guys ever do anything resembling work?

We’re going to keep this section brief, mostly because we’ve already covered everything you need to know. Everything except this: If you want to move a file or folder rather than copy it, follow all the instructions above for copying files and folders but replace the word Copy with the word Move. For example, here’s our script to copy a file using the Copy method:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

objFile.Copy "C:\scripts\temp\"

To move that file rather than copy it - in other words, to remove the file test.txt from the C:\scripts folder and put it in the C:\scripts\temp folder instead, simply replace the Copy method with the Move method:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

objFile.Move "C:\scripts\temp\"

Okay, what we just said isn’t entirely true. Other than the obvious fact that Move moves and Copy copies, there’s one big difference between these methods that you need to know about. While the Copy method accepts a second parameter that determines whether or not an existing file is overwritten - with a default of True - the Move method doesn’t accept any other parameters. Not only that, but the default, and, in this case, the only behavior is just the opposite. If you run the script we just showed you and the file test.txt already exists in C:\scripts\temp, the file will not be moved and you’ll receive an error message:

C:\scripts\test.vbs(4, 1) Microsoft VBScript runtime error: File already exists

The same is true of the MoveFile and MoveFolder methods. They take the same parameters as the CopyFile and CopyFolder methods, with the exception of the overwrite parameter, which isn’t available with the MoveFile and MoveFolder methods. Otherwise they’re basically the same, only moving the file or folder to the destination rather than copying it:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "C:\scripts\test.txt","C:\scripts\temp\"

As you can see, we pass the file we want to move (C:\scripts\test.txt) and the destination we want to move it to (C:\scripts\temp) to the MoveFile method. The same goes for the MoveFolder method:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFolder "C:\scripts","C:\scriptstest"

Also, just like the CopyFile and CopyFolder methods, the MoveFile and MoveFolder methods allow you to use wildcards to specify more than one file or folder at a time. Here’s an example:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "C:\scripts\*.txt","C:\scripts\temp\"

This script moves all files ending in .txt from the C:\scripts folder to the C:\scripts\temp folder. And one more reminder: if the file by the same name already exists in the destination location the file won’t be moved and you’ll receive an error.

Delete Files and Folders

Question 4: If you have an attorney representing you in this matter, please provide their name, address and phone number.

Interesting how the question about attorneys in the subrogation process came up in the Delete section…

Believe it or not (and why wouldn’t you believe it?), deleting files and folders is as simple as copying and moving files and folders. Let’s see, we’ve seen the Copy, CopyFile, and CopyFolder methods, and the Move, MoveFile, and MoveFolder methods…take a wild guess as to what the names of the three delete methods are. Yes, you’re brilliant: Delete, DeleteFile and DeleteFolder. (We won’t speculate on what you are if you actually missed that one.) The Delete method deletes a specific file or folder. Here’s the script:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\temp\test.txt")

objFile.Delete

As usual, we start by creating a FileSystemObject. We then get an object reference to the file C:\scripts\temp\test.txt. We call the Delete method on that object, and the file is deleted. Simple. You’ll notice that we didn’t pass any parameters to the Delete method. This method actually does accept one parameter, which must be a value of either True or False. Passing True to the Delete method specifies that the file should be deleted even if it’s read-only. The default is False, meaning that if you leave out this parameter or pass False and the file you’re trying to delete is read-only, you’ll receive an error message and the file won’t be deleted:

C:\scripts\test.vbs(4, 1) Microsoft VBScript runtime error: Permission denied

You can also delete an entire folder, including all its contents:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\scripts\temp")

objFolder.Delete

In this case we get an object reference to the C:\scripts\temp folder and call the Delete method on that object in order to delete that folder. If there are files and folders within that folder, they’ll all be deleted. The only exception: a file or folder marked as read-only. If any of the files or folders within the folder to be deleted are read-only, they won’t be deleted and neither will the folder. However, it’s important to note that all files and folders are deleted one at a time until they’ve all been deleted or - and this is the important part - until the script runs into a read-only file or folder. If that happens the script stops with an error. That means your folder could still be there with some of the files and folders left in it, but not all of them; it’s not an all-or-nothing deal. You can force a delete of everything, including the read-only files and folders, by passing True to the Delete method:

objFolder.Delete True

Important: You might think that you could simply insert an On Error Resume Next statement and the script would then bypass the read-only file or folder and move on to the next one and continue deleting. That’s a logical assumption, but, unfortunately, that’s not the way it works. In this case the FileSystemObject completely ignores the On Error Resume Next: if you run into an error the Delete method simply stops. If you have anything following the call to the Delete method, such as a Wscript.Echo statement, the remaining code will run and you won’t see any error messages, but you would still have deleted only up to the point where the read-only file was found.

Just like with copy and move, you can delete sets of files and folders using wildcards and the file- and folder-specific implementations of the methods, in this case DeleteFile and DeleteFolder. Here’s an example using DeleteFile:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.DeleteFile "C:\scripts\temp\*.txt"

This script deletes all files in the C:\scipts\temp folder that end with .txt. As with the Delete method, DeleteFile also takes an additional parameter specifying whether to force the deletion of read-only files. The default is False, don’t delete read-only files.

And here’s how you delete a bunch of folders:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.DeleteFolder "C:\scripts\x*"

This script deletes all folders (and their contents) that begin with the letter x from the C:\scripts folder. Be careful with this, and all the delete methods. You don’t get a warning asking if you really want to delete (not even in Windows Vista, believe it or not). So why be careful? Well, suppose you run a script like this:

Set objFSO = CreateObject("Scripting.FileSystemObject")
' objFSO.DeleteFolder "C:\w*"
you could wipe out some of your Windows files. Especially if you add this:
Set objFSO = CreateObject("Scripting.FileSystemObject")
' objFSO.DeleteFolder "C:\w*", True

We’ve actually added a comment marker in front of the DeleteFolder call in these last two scripts; we know some of you get a little overanxious and might just copy the scripts and run them, then read about them later. That would be a mistake in this case, at least if we had left out the comment mark. Without the comment this script would delete all folders in your C: drive that started with w (like, say, C:\windows), as well the contents of those folders, even those that are read-only.

Copy by Date

Question 5: Please indicate the date and time that the injury and/or condition occurred.

Sometime during the ninja attack.

One of the interesting things you can do with the FileSystemObject is retrieve various types of date information about files and folders. Here’s how you get the date a file was created:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

Wscript.Echo objFile.DateCreated

The first two lines in this script should be pretty familiar to you by now: we create a reference to the FileSystemObject, then get an object reference to the test.txt file in the C:\scripts folder:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

Next, we use the DateCreated property of the File object to echo the date the file was created:

Wscript.Echo objFile.DateCreated

This returns a date and time value that looks something like this:

3/22/2007 11:07:23 AM

You can also retrieve the date the file was last accessed by using the DateLastAccessed property:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

Wscript.Echo objFile.DateLastAccessed

Or the date the file was last modified by looking at the DateLastModified property:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile("C:\scripts\test.txt")

Wscript.Echo objFile.DateLastModified

These properties correspond to the dates you see when you look at the file properties:

File Properties

You might see where we’re going with this discussion. Yes, getting these dates can be useful, we’re glad you told us about these properties, but…what can we do with them? Well, how about copying all the files created more than a month ago from the C:\scripts folder to the C:\scripts\old folder:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\scripts")

Set colFiles = objFolder.Files

dtmMonthAgo = DateAdd("m", -1, Now)
 
For Each objFile in colFiles
    If objFile.DateCreated < dtmMonthAgo Then
        objFSO.CopyFile objFile.Path, "C:\scripts\old\"
    End If
Next

We start this script by getting a FileSystemObject, then get an object reference to the folder C:\scripts:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\scripts")

We need to look at all the files in this folder, so we use the Files method to get a collection of all the files in the C:\scripts folder:

Set colFiles = objFolder.Files

You’ll recognize the next line if you read last month’s Sesame Script. We want to find all the files created more than one month ago. That means we need to find out when one month ago was. We do that using the DateAdd function:

dtmMonthAgo = DateAdd("m", -1, Now)

We passed three parameters to DateAdd:

  • "m" - Specifies that we want to add to the month part of the date.

  • -1 - You’ve probably noticed that even though we want to go back one month, we’re using the DateAdd function. That’s because there’s no DateSubtract function. But that’s okay, all we have to do is add a negative number and suddenly we’re subtracting. So to go back one month we add negative 1.

  • Now - This is simply a VBScript function that returns the current system date and time.

We store the new date, the date from exactly one month ago, in the variable dtmMonthAgo. Now it’s time to go through out collection of files. We do that with a For Each statement:

For Each objFile in colFiles

This just says that, for every file in our collection of files, we’re going to do something. What is that something? This:

If objFile.DateCreated < dtmMonthAgo Then
        objFSO.CopyFile objFile.Path, "C:\scripts\old\"
    End If

We start with an If statement where we compare the DateCreated property of the file with the date from one month ago, dtmMonthAgo. If DateCreated is less than dtmMonthAgo, that means the file was created more than one month ago and we want to copy it to the C:\scripts\old folder. Remember way back at the beginning of this article, the part where we talked about the CopyFile method? Good; that means you already know what we’re doing here. We’re calling CopyFile and passing it the full file path (which just happen to be stored in the Path property of the File object) and the destination folder where we want to copy the file.

We then loop around and check the next file in the collection. This continues until we’ve looked through all the files and copied over those that were created more than one month ago.

It’s All Yours

Question 6: Is another party responsible for this accident?

Nope, it had nothing to do with a party.

You might not realize it now, but we’ve just given you everything you need to copy, move, and delete files based on date. You say we only showed you how to copy files more than a month old? Technically that’s true. But all the pieces are there: you know how to copy, move, and delete; you know how to retrieve dates; and you know how to read through a list of files in a folder. What more could you ask for?

We know, you’ll think of something. But that’s okay, that’s what we’re here for. But for now the subrogation process has come to an end and it’s time to pay the bills. See you next month.

Epilogue: For those of you who are interested, here’s the actual definition of subrogation (from the American Heritage Dictionary): The substitution of one person for another, especially the legal doctrine of substituting one creditor for another.

Cleared that right up, didn’t it?