Files are the building blocks of any application running under any OS. Files are also the software elements that administrators and users manipulate most of their workday. However, none of the Windows file systems (e.g., FAT, NTFS) follow an object-oriented schema. In other words, Windows file systems don't consider a file (or a folder) as an object with a fixed programming interface. To make Windows file systems recognize a file as an object, you need to use a tool such as the File System Object (FSO) model. With the FSO model's File object, you can manipulate files in VBScript applications.
The File object represents a file in a Windows file system. After you access the File object, you can use the object's methods and properties to work with it. The File object has 12 properties that provide information about files and four methods that manipulate files.
Accessing the File Object
To work with a File object, you need a reference to it. You can obtain this reference in two ways, both of which rely on the FileSystemObject object. First, you can call the FileSystemObject object's GetFile method and specify the fully qualified filename (i.e., the absolute or relative path) of the file you want to access. Second, you can enumerate the items in the FileSystemObject object's Files collection and stop at the element whose properties match your criteria. Let's examine the pros and cons of both techniques.
Using GetFile is the most common technique. This method takes one argument: the absolute or relative path to the file you want. If you specify the absolute path, the method returns a reference to the specified file in the specified directory. For example, the code
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set file = fso.GetFile _ ("C:\mydir\myfile.ext")
returns a reference to the myfile.ext file in the MyDir folder on the C drive. If you specify the relative path, the method returns a reference to the specified file in the current directory. For example, the code
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set file = fso.GetFile _ ("myfiles\myfile.ext")
returns a reference to the myfile.ext file in the MyFiles folder in the current directory. When you run VBScript code through the Windows Script Host (WSH) environment, the current directory is the one that contains the script file. Microsoft designed WSH this way for efficiency—you just have to specify the relative path in the script.
GetFile can't handle ambiguous file specifications (i.e., filenames that can't be resolved in terms of a unique file). For this reason, you can't pass filenames with wildcards to GetFile. For example, if you run the code
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set file = _ fso.GetFile("C:\*.bat")
you'll receive the error message File not found.
If you need to scan all the files in a given folder, you use the Files collection technique. As the following code shows, you access the Files collection through the Folder object that I discussed last month:
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set f = _ fso.GetFolder("C:\mydir") For Each file In f.Files MsgBox f.Name Next
The code loops through all the files in the My Dir folder. Each item in the Files collection evaluates to a File object.
Accessing the File Object's Properties
Many characteristics (e.g., name, location, size, type, creation date) help identify a file. The File object's properties let you retrieve those characteristics. To access a property, you use the syntax
where fileObject is the referenced File object and Property is the property's name.
As Table 1 shows, the File object has 12 properties. You use the Drive and ParentFolder properties to identify a file's location in terms of its drive and parent folder (i.e., the folder that contains the file), respectively. You can use the Path property to obtain a file's fully qualified path or the ShortPath property to obtain the 8.3 version of the path (i.e., a path containing an 8-character filename with a 3-character extension). You can use the ShortName property to retrieve the 8.3 version of the filename.
The Size property returns a number specifying how many bytes a file is. The Type property returns a string that specifies the folder's type (i.e., the short description that Windows Explorer displays in its Type column in the Details view).
Any file system element is characterized by one or more dates. With the DateCreated, DateLastAccessed, and DateLastModified properties, you can access a file's date of creation, last access, and last modification, respectively. An important point to consider when you're using the DateCreated property is that a file's creation date changes if you move the file from one machine to another. Windows' creation date isn't a per-file attribute that the file retains for its life cycle. Rather, the creation date is a per-system attribute that disappears when you copy the file to another storage medium.
Unlike the other properties, the Attributes and Name properties are read/write. Here's how you assign attributes and filenames to a File object:
The Attributes property. File attributes are the only information that the file system stores about a file. You use attributes to specify, for example, that a file is hidden or read-only. Table 2 lists the attributes that are relevant to files. To set an Attributes property, you use the property's optional newattributes argument, which has the syntax
fileObject.Attributes _ \[= newattributes\]
where newattributes is the new Attributes value you want the file to have. The Attributes value is a bitmask—that is, a numeric value whose meaning is determined by each bit's binary value. For the File object, the first bit is a constant with the value of 0. In other words, you can't set this bit programmatically. The second bit marks the file as read-only or read/write, depending on the bit's value. If the second bit is 0, the file is read/write; otherwise, it's read-only. Thus, for example, the code
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set file = _ fso.GetFile("C:\foo.txt") file.Attributes = 1
makes foo.txt a read-only file. The same scheme applies to all the other bits. (For more information about bitmask values, see my March 2000 column.)
Because Attributes is a bitmask value, setting this property to a new value removes all existing attributes. For example, if foo.txt is a systems file and you set its Attributes property to 1, foo.txt doesn't become a read-only systems file but rather a read-only normal file.
If you want to preserve some of the existing attributes, a better approach is to use code like that in Listing 1. This code uses an If...Then...Else statement to determine whether foo.txt is read-only. If not (i.e., the file is read/write), the code changes that attribute to read-only. This change doesn't affect any other file attributes. Thus, foo.txt becomes a read-only systems file.
The Name property. To assign a value to the Name property, you use the syntax
fileObject.Name \[= newname\]
where newname is the new filename. You can use the Name property to indirectly rename files. (Microsoft didn't create a property or method in the FSO model that directly renames files.) The user-defined function called RenameFile in Listing 2 uses the GetFile method to retrieve the file you want to rename and the Name property to assign the new filename.
Using the File Object's Methods
The File object has four methods: Copy, Delete, Move, and OpenAsTextStream. The Copy method's syntax is
fileObject.Copy destination _ \[, overwrite\]
where destination is the location of the file after you duplicate it and overwrite is an optional argument that tells the method not to overwrite any existing file. By default, the Copy method overwrites existing files. You can change this default setting by specifying False (value of 0) for the overwrite argument with code such as
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set MyFile = _ fso.GetFile("C:\foo.txt") MyFile.Copy "C:\foo2.txt", 0
This code duplicates the file that the MyFile variable points to (foo.txt) in the same folder (the root of the C drive) but gives the file a different name (foo2.txt). If a file named foo2.txt is already in the folder, you'll receive the error message File already exists.
The Delete method's syntax is
where force is an optional argument that tells the method to delete read-only files. By default, the Delete method doesn't delete read-only files. To change this default setting, you specify True (value of 1) for the force argument with code such as
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set MyFile = _ fso.GetFile("C:\foo.txt") MyFile.Delete 1
The Move method performs the copy and delete functions in one operation. Its syntax is
where destination is the location to which you want to move the file. For example, the code
Set fso = CreateObject _ ("Scripting.FileSystemObject") Set MyFile = _ fso.GetFile("C:\foo.txt") MyFile.Move "C:\my documents\foo.txt"
moves foo.txt from the root of the C drive to the My Documents folder on the C drive.
The File object's Copy and Move methods don't accept wildcards. Therein lies the difference between these methods and the FileSystemObject object's Copy and Move methods. Both objects' methods achieve the same results. However, the FileSystemObject object's methods are more efficient because you can use wildcards to copy and move more than one file at a time.
The OpenAsTextStream method provides a means to access and edit a file's content. Unlike the other three methods, OpenAsTextStream returns an object. (i.e., the TextStream object) Next month, I'll discuss the OpenAsTextStream method when I cover the TextStream object.
To better understand how to use the File object's properties and methods, consider this example. Suppose you want to create a script that outputs a directory listing for a specified folder. You want the listing to specify each file's name, size, and attributes only.
You can use the FSO model's File and Folder objects to develop a customized directory listing. As Listing 3 shows, you begin the script by declaring the constants and setting the folderName variable to the folder you want the directory listing for (in this case, the root of the C drive). Because you want to scan all the files in the specified folder, you obtain a reference to the Files collection and set that reference to the files variable.
Next, you use a For Each...Next statement to loop through each file (f) in the files variable and apply the Name, Size, and Attributes properties to obtain the needed information. The code FormatAttrib(f.Attributes) calls the FormatAttrib function. This user-defined function converts the numeric attribute values (e.g., 2) into descriptive text (e.g., Hidden) so that the file attributes in the directory listing are easier to understand. After the script loops through all the files, the results appear in a message box like that in Screen 1.
More Tools in Your Toolbox
The File object's 12 properties and its Copy, Delete, and Move methods let you access, manipulate, and learn about files. However, these properties and methods don't let you access and manipulate the content of files. To work with the content, you need to use the File object's OpenAsTextStream method to access the TextStream object. Next month, I'll show you how to use this method and object to open files and write lines of text to them.
- The fourth code example in the text contains an error. The code should read:
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder("C:\mydir")
For Each file In f.Files