In this series of articles we’ll take a close look at dealing with files and folders in WSH. There are a few different ways to do this. First we’re going to take a look at WSH’s native way of doing this by using the FileSystemObject.
The FilesSystemObject is VBScript’s way of working directly with the file system. It provides methods and properties for handling and manipulating files and folders. You can create, move, and delete files and folders as well as check and change some attributes.
You should already be familiar with connecting to the FileSystemObject. In VBScript it looks like this:
Set objFso = CreateObject("Scripting.FileSystemObject")
The above code uses the Wscript object’s CreateObject method to get a handle on the FileSystemObject. The beauty of the FileSystemObject is that the ActiveX control can automatically detect the type of file system and work with it. The FileSystemObject can work with any file system supported on your system.
The FileSystemObject works with the native drivers to control the file system. That means if you were to add support for some non-Windows file system such as ext3, then the FileSystemObject would support it inherently.
Keep in mind when creating scripts that deal with the file system, sometimes these processes can take a while. It’s not unusual to take up to 10 minutes or more to enumerate the files and folders on a typical drive that is near capacity. Of course, there are a lot of factors that play into this: drive seek speed, bus speed, processor speed, available memory, and background processes just to name a few. Some files systems are faster than others simply by design.
In short, a little error-handling and some pre-design thought can go a long way.
Before diving into your script, you should also take a couple other things into consideration. Will your script be running locally or remotely? And will you be using this script on multiple hosts or always running it from the same location? These things can affect the way that you handle folder paths. We’ll deal more with these later.
Let’s do some basic stuff. We’ll begin by listing the content of our root drive. Let’s see what folders we have there. Now would probably be a good time to take a look at the properties and methods available to us.
Methods
object.BuildPath(Path, Name)
object.GetFile(Name)
object.GetFolder(Folder)
Properties
object.Subfolders
object.Files
object.Name
object.Path
Our code construct is very simple. We’ll use the GetFolder method to get a handle on the C: folder. Then we’ll loop through the folders and return their names. The code looks something like this:
Set objFolder = objFso.GetFolder("C:")
Set colFolders = objFolder.Subfolders
For Each folder In colFolders
Wscript.Echo folder.Name
Next
The FileSystemObject’s Subfolders property returns a collection of subfolders under the path that we specify. Because collections act like objects, we have to use a Set statement. Looping a collection is very easy with VBScript’s For Each statement. It simply returns each object in a collection one at a time until they have all been used.
A simple Echo is used to display the folder name. The Name property returns a string containing the folder object’s name. If you were to run this script using Cscript.exe, you’re output should look something like this:
Documents and Settings
Program Files
RECYCLER
System Volume Information
WINDOWS
Notice that our script returned both RECYCLER and System Volume Information. Both of these are protected system folders. You can see from this quick example just how powerful this can be.
I’m using Cscript in these examples to avoid having to click OK on a bunch of message boxes. It also allows me to demonstrate my results more easily.
A little code change and we can list our files just as easily. We’ll just trade out the folder objects for file objects.
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.GetFolder("C:")
Set colFiles = objFolder.Files
For Each file In colFiles
Wscript.Echo file.Name
Next
We use the GetFolder property to connect to the root folder. Then, the Files property returns a collection of files in that folder. We used the same looping technique to enumerate the files. Again, with Cscript you should see something like this:
AUTOEXEC.BAT
boot.ini
CONFIG.SYS
IO.SYS
MSDOS.SYS
NETDETECT.COM
ntldr
pagefile.sys
Again, you can see that our script easily returned several protected system files. Remember that WSH works on a low level behind most of Windows’ protection features. You can easily damage your system if you are not careful. I recommend running scripts like this against test systems or directories before actually deploying them.
Okay, enumerating files and folders is all well and good, but let’s do something a little more useful. Chances are that if you are scripting files and folders you are most likely interested in performing actions on them. Common actions include moving, copying, and deleting. So let’s start there. As you probably expect, the FileSystemObject provides methods for doing all of these and more.
We’re going to create a basic script that will create a folder and a add a couple of text files to it so that we have some files to work with.
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.CreateFolder("C:TestFolder")
For x = 1 to 5
strName = "test" & x & ".txt"
objFolder.CreateTextFile strName
Next
Now you should have a folder at C:TestFolder that has five text files named test1.txt through test5.txt. Now we’ll create a second folder called TestFolder2 and copy our text files to that location.
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objSrc = objFso.GetFolder("C:TestFolder")
Set objDest = objFso.CreateFolder("C:TestFolder2")
I’ve taken a little roundabout way of doing this so that I could demonstrate a few more properties and methods. You can see that I’ve constructed my file names and paths completely using the properties available to me. Just remember that all of these methods accept either objects or strings as their parameters and construct your code accordingly.
In this case, CopyFile accepts two string parameters. The first is the full path of our source file to copy, and the second is the full path to the destination. We pass our source with file.path. The path property returns a full path as a string so we can use that for our first parameter.
To avoid some confusion, this is what our properties actually return: file.Path returns “C:\test.txt” objDest.Path returns “C:\TestFolder2” file.Name returns “text.txt”
The second parameter requires a full path to the destination file. Since we just created that folder, we need to construct a string to use. So we use the objDest.Path and file.Name properties. We’ve just concatenated them. Don’t forget to add the extra backslash (\) because objDest.Path does not return a trailing slash on our folder.
There is a second way to accomplish this same task. In the last code example, we used just the methods and properties of the FileSystemObject. However, as we’ve seen, the FileSystemObject also contains File and Folder objects. Each of these objects also contains methods and properties that we can use.
Many of the methods and properties are shared by both the File object and the Folder object. Most of these methods and properties are self explanatory so I’m not going into too much detail in an effort to save space.
Each of these methods and properties returns a string, an object, or a collection with the exception of Copy, Delete, and Move.
However, there are a couple of points I want to make. First, the Attributes property will either get or change the attributes of a file or folder based on whether or not a parameter is supplied. You should also note that the ParentFolder property returns an object. (It actually performs a GetFolder on the parent folder). The OpenAsTextStream method also returns an object. And finally, both the Files property and the SubFolders property return collections.
Keeping these things in mind, let’s rewrite our last code example. This time we’ll create a third folder and move the files from the second to the third. Then we’ll delete the empty folder. To make things interesting, I’m only going to reference one file from the second folder. This will give us a chance to see some of the other properties in action. Obviously, I wouldn’t do this in a real world situation.
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder3 = objFso.CreateFolder("C:TestFolder3")
Set objFile = objFso.GetFile("C:TestFolder2test1.txt")
Set objFolder2 = objFile.ParentFolder
For Each file In objFolder2.Files
file.Move objFolder3.Path & "" & file.Name
Next
objFolder2.Delete
At this point, you should be able to see exactly what this code is doing. First we create our new folder. Next, we use the GetFile method to get a handle on our file. Then we use the ParentFolder property to get a handle on its parent folder. Remember to use the Set statement since the ParentFolder returns an actual object and not a string.
Once we have a handle on our second folder, set up a loop to grab each file and move it to the new folder. We finish up by simply deleting the second folder.
If you’ve been following along, at this point you should have two folders, TestFolder and TestFolder3, both containing the exact same files.
In part two of this series we’ll take a look at some of the more advanced methods and properties that the FileSystemObject has to offer. In the meantime, play around with this a bit.
You’ll begin to see that every task for which you write code can be accomplished in two or three other ways. That goes to show the flexibility that VBScript and WSH have.
I’m sure someone at this point is wondering how to rename files and folders, right? I’ve shown you all of the basic file operations except that. Well, here’s why. Think about what a rename really is.
At the file or folder level, the computer must make a copy of the original file with a new name and then delete the first. There is no need to have another method for this when we can perform the same procedure with the ones we have.
The simplest way to perform a file (or folder) rename is to use the corresponding move method. Just supply the new filename for the destination. Here’s a quick example of how to rename C:text1.txt into C:text2.txt
Set objFso = CreateObject("Scripting.FileSystemObject")
objFso.MoveFile "C:text1.txt", "C:text2.txt"
Believe me when I tell you that we’ve barely scratched the surface. Stick around for part two of this series and learn some of the cool tricks that the FileSystemObject can do. You won’t want to miss it. Until next time, keep coding!