When I first started working with files and folders in Windows Script Host (WSH), I discovered that programming simple command-shell tasks in scripts required a significant amount of code. One culprit behind the large code requirement is FileSystemObject, the root object of the File System Object (FSO) model, which you can use in VBScript code to manipulate Windows file systems. FileSystemObject isn't part of WSH; rather, it's included in the Microsoft Scripting Runtime Library. Although FileSystemObject is flexible, it forces you to write many lines of code to perform even mundane activities, such as reading or writing to a file, appending data to a file, and creating a directory tree.
Fortunately, administrators perform most common file- and folder-manipulation tasks in the same specific ways. I wrote a set of custom VBScript functions to perform such repetitive tasks. Each function solves a particular problem and lets you focus on coding the nonrepetitive parts of your scripting solutions. Simply paste the functions into your VBScript script and call them to perform repetitive tasks. Two Web-exclusive sidebars—"Read the Last Few Lines of a File," which includes an additional VBScript function, and "Write Your Own Plug-In Functions," which provides guidelines for writing plug-in functions—are available at http://www.winnetmag.com/windowsscripting, InstantDoc IDs 42461 and 42462, respectively.
1. Read a Text File
The ReadFile(ByVal FilePath) function, which Listing 1 shows, reads an entire file. ReadFile identifies standard Unicode text files and reads them into a variable. ReadFile is similar in functionality to the Type command that you use at a command prompt.
The following code provides an example of how to call the ReadFile function in a script:
data = ReadFile _ ("C:\windows\setup.log")
This code calls ReadFile to read the contents of the C:\windows\setup.log file into the data variable.
If a file doesn't exist or is empty, ReadFile returns a vbEmpty value. When you add the code
If IsEmpty(data) _ Then WScript.Quit
after the ReadFile call, the script will end if the file doesn't exist or contains no data.
If your text files use standard Windows line endings, you can add code that will turn the ReadFile function's output into an array of lines. Simply add the following code after the ReadFile call to split the returned data at the line endings:
data = _ Split(ReadFile("C:\boot.ini") _ vbNewLine)
To display the returned data (in this case, the contents of the boot.ini file) on the console as an array of lines, add the following code to your script:
data = ReadFile(C:\boot.ini) For Each line In data WScript.Echo line Next For Each line In data WScript.Echo line Next
2. Write to a Text File
You can use the WriteFile(ByVal FilePath, ByVal Text) function, which Listing 2 shows, to write text to a text file. If the file doesn't already exist, Write-File creates it in the system default text file format (ANSI or Unicode).
The following code provides an example of how to call the WriteFile function:
WriteFile("C:\tmp\script.log", _ "write test succeeded")
This code calls WriteFile to write the string write test succeeded to the C:\tmp\script.log file.
The WriteFile function returns a value of True if it writes to the file successfully; otherwise, it returns False. Thus, WriteFile lets you easily handle file-writing problems in scripts. For example, you can use the following code to call the function and perform a test based on whether the write operation succeeded:
If Not WriteFile("C:\tmp\script.log", _ "write test succeeded") Then ' Code to handle the problem End If
The WriteFile function provides little feedback about the cause of an error, whereas FileSystemObject typically provides limited feedback. The most common causes of errors other than a nonexistent parent folder are locked files and insufficient permissions. Both problems yield identical Permission Denied errors. The MakeDirectory(ByVal Path) function, which I discuss later, eliminates the problem of nonexistent parent folders.
3. Append Data to a File
The AppendFile(ByVal FilePath, ByVal Text) function, which Listing 3 shows, is similar to WriteFile. The only significant difference is that AppendFile always opens a file and appends text to the end of the file rather than overwriting any existing text. If the file doesn't exist, AppendFile creates it, just as using right angle brackets (>>) to redirect output from a command-line program creates a new file instead of trying to append text to a nonexistent file.
To call AppendFile, you specify two arguments: the target file and the text to write to that file. For example, the call
Call AppendFile ("C:\users.txt", _ "John.Doe")
writes the string John.Doe to the C:\users.txt file. Note that this function appends the specified text to the end of the last line in the file—it doesn't insert any line returns. For example, the code
Call AppendFile("C:\users.txt", _ "John.Doe") Call AppendFile("C:\users.txt", _ "Mike.Smith")
causes the file's content to look like
If you want each entry on a separate line, you can concatenate the vbNew-Line constant to the code like this:
Call AppendFile("C:\users.txt", _ "John.Doe") & vbNewLine Call AppendFile("C:\users.txt", _ "Mike.Smith") & vbNewLine
4. Read the First Few Lines of a File
I named the Head(ByVal FilePath, ByVal LineCount) function, which Listing 4 shows, after a UNIX tool that performs the same task: reading the first few lines of a file. To call the function, you specify the target file and the number of lines you want to read. For example, to have the Head function read the first 10 lines from the C:\windows\xpsp1hfm.log file, you use the call
Call Head("C:\windows\"& _ "xpsp1hfm.log", 10)
5. Create an Entire Directory Tree in One Step
The command-shell Mkdir (or Md) command recursively creates all necessary folders in an entire tree. In other words, if you run the command
Mkdir automatically creates C:\tmplogs and C:\tmplogs\2004 if they don't exist. For unknown reasons, Microsoft didn't design the CreateFolder method in the FSO model to create folders as Mkdir does; CreateFolder merely returns the error message Path not found when a folder doesn't exist.
The MakeDirectory(ByVal Path) function, which Listing 5 shows, automatically creates an entire directory tree if necessary. The function assumes that you simply want to make sure the necessary folders exist, that you don't care whether they already exist, and that you don't care whether the function must create one or more containing folders. When a folder already exists or MakeDirectory successfully creates it, MakeDirectory returns a value of True. If MakeDirectory can't create the folder path (e.g., because of insufficient permissions, because the drive or network path you're starting from doesn't exist), the function returns False.
To call MakeDirectory, you simply specify the folder path as the only argument. For example, to create the folder C:\users\john.doe\mail, even if folder C:\users doesn't exist, just add the following code to your script:
rtn = MakeDirectory _ ("C:\users\john.doe\mail")
MakeDirectory then creates the entire tree of folders in one step.
Plug In to Easier Scripting
You now have five handy functions that automate some tedious aspects of handling files and folders in VBScript code. These functions can save you time by eliminating repetitive coding. I hope they inspire you to create your own VBScript plugins!