The FileSystemObject provides a modern, convenient, object-oriented, and coherent way to access the file system from many of the scripting environments used with the AWR Design Environment. While many environments including the built-in basic provide means for opening, reading and writing files the file system object provided by the Microsoft Scripting Library, the library that also contains the dictionary object, provides a more comprehensive solution to file manipulation.
The FileSystemObject provides a objects arranged in a hierarchy consistent with the elements of the file system. The objects of this hierarchy are shown below in Figure 1.
Figure 1: FileSystemObject Object Hierarchy
To use the FileSystemObject you will first need to add a reference to the Microsoft Scripting Library. In the AWR scripting environment select the References toolbar button. And then in the dialog find the Microsoft Scripting Runtime item and place a check next to the entry as shown in Figure 2.
![]() | |
(A) Select the References Toolbar Button | (B) References Dialog Select the Microsoft Scripting Runtime |
Figure 2 Adding a reference to the Microsoft Scripting Runtime.
At the root of the hierarchy is the FileSystemObject object itself. It exposes many methods and only one property, Drives, which returns a collection of all the drives in the system. The FileSystemObject object (abbreviated as FSO in the following text and code) is the only creatable object in the hierarchy – that is, it's the only that can be declared using the New keyword. All the other objects are dependent objects that derived from this one and are exposed in the form of properties or methods. See how easy it is to fill an array with the list of all the ready drives in their capacities:
Sub Main
Dim fso As Scripting.FileSystemObject
Dim dr As Scripting.Drive
Set fso = New Scripting.FileSystemObject
' Needed for not ready drives.
On Error Resume Next
Debug.Clear
For Each dr In fso.Drives
Debug.Print dr.DriveLetter & " [ " & dr.TotalSize & " ] "
Next dr
End Sub
Table 1 below summaries the many methods exposed by the FileSystemObject. A few of them are also available (often with different names and syntax) as methods of the secondary Folder and File objects. Most of these methods add functionality to commands already present in the in the built Basic. For example, you can delete non-empty folders (be very careful!) and copy and rename multiple files and directories with a single command. You can easily extract portions of a filename without having to write special routines.
Syntax | Description |
---|---|
BuildPath(Path,Name) | Returns a complete filename, obtained by concatenating the path (relative or absolute) and name. |
CopyFile(Source,Destination,[Overwrite]) | Copies one or more files: Source can include wildcards, and Destination is considered be a directory if it ends with a backslash. It overwrites files unless you set Overwrite to false. |
CopyFolder(Source,Destination,[Overwrite]) | Same as CopyFile, but copies entire folder with their contents (sub-folders and files). If Destination doesn't correspond to an existing directory, it's created (but not of Source contains wildcards. |
CreateFolder(Path) As Folder | Creates a new Folder object and returns it; raises an error if the folder already exists |
CreateTextFile(FileName,[Overwrite],[Unicode]) As TextStream | Creates a new TextFile object and returns it; set Overwrite = False to avoid overwriting existing file; set Unicode = True to create a Unicode TextFile object. |
DeleteFile(FileSpec,[Force]) | Deletes one or more files. FileSpec can include wildcards; Set Force = True to force deletion of read-only files |
DeleteFolder(FolderSpec,[Force]) | Deletes one or more Folders, together with their contents; set Force = True to force delete of read-only files |
DriveExists(DriveName) | Returns True if a given logical drive exits |
FileExits(FileName) | Returns True if a given file exists (The path can be relative to to the current directory.) |
FolderExists(FolderName) | Returns True if the given folder exists (The path can be relative to the current directory.) |
GetAbsolutePathName(Path) | Converts a path relative to the current directory into an absolute path. |
GetBaseName(FileName) | Extract the base filename (without its path and extension); it doesn't check whether the file and/or the path actually exists. |
GetDrive(DriveName) As Drive | Returns the Drive object that corresponds to the letter or the UNC path passed as an argument. (It checks that the drive actually exists). |
GetDriveName(Path) | Extracts the Drive from the path. |
GetExtensionName(Path) | Extracts the extension string from a filename. |
GetFile(FileName) | Returns the File object corresponding to the name passed as the argument. (Can be absolute or relative to the current directory) |
GetFileName(Path) | Extract the filename (without its path but with its extension); it doesn't check whether the file and/or path actually exists. |
GetFolder(FolderName) As Folder | Returns the Folder object corresponding to the path passed as the argument (Can be absolute or relative to the current directory) |
GetParentFolderName(Path) | Returns the name of the parent directory of the directory passed as teh argument (or an empty string if the parent directory doesn't exist.) |
GetSpecialFolder(SpecialFolder) As Folder | Returns a folder object that corresponds to one of the special Windows directories. SpecialFolder can be 0-WindowsFolder, 1-SystemFolder, 2-TemporaryFolder. |
GetTempName() | Returns the name of a non-existent file that can be used as a temporary file |
MoveFile(Source,Destination) | Same as CopyFile, but it deletes the source file. It can also move among different drives, if this function is supported by the operating system |
MoveFolder(Source,Destination) | Same as MoveFile but works on directories instead. |
OpenTextFile(FileName,[IOMode],[Create],[Format]) As TextStream | Opens a text file and returns the corresponding TextStream object. IOMode can be one or a combination (use the OR operator) of the following constants: 1-ForReading, 2-ForWriting, 8-ForAppending; set Create to True if you want ot create a new file; Format can be 0-TristateFalse (ANSI), 1-TristateTrue (Unicode) or 2-TristateUseDefault (determined by the operating system). |
Table 1: All the methods of the FileSystemObject object.
The Drive object exposes only properties (no methods), all of which are summarized in Table 2. All the properties are read-only, except the VolumeName property. The following short code snippet determines the local drives that are ready and have at least 100MB of free space on them.
Sub Main
Dim fso As Scripting.FileSystemObject
Dim dr As Scripting.Drive
' Get a FileSystemObject instance
Set fso = New Scripting.FileSystemObject
Debug.Clear
For Each dr In fso.Drives
If dr.IsReady Then
If dr.DriveType = Fixed Or dr.DriveType = Removeable Then
If dr.FreeSpace > 100 * 2 ^ 20 Then
Debug.Print dr.Path & " [ " & dr.VolumeName & " ] = " & dr.FreeSpace
End If
End If
End If
Next dr
End Sub
Table 2 summaries the properties exposed by the Drive object.
Syntax | Description |
---|---|
AvailableSpace | The free space on the drive, in bytes; it usually coincides with the value returned by the FreeSpace property, unless the operating system supports disk quotes |
DriveLetter | The letter associated with the drive or an empty string for network drives not associated with a letter |
DriveType | A constant that indicates the type of the drive: 0-Unknown, 1-Removable, 2-Fixed, 3-Remote, 4-CDROM,5-RamDisk |
FileSystem | A string that describes the file system in use: FAT, NTFS, CDFS |
FreeSpace | The free space on the drive (See AvialableSpace) |
IsReady | True if the drive is ready, False otherwise |
Path | The path associated with the drive, without the backslash (for example C:) |
RootFolder | The folder that corresponds to the root directory |
SerialNumber | A long number that corresponds to the serial disk number. |
ShareName | The network shared name for the drive or an empty string if it isn't a network drive. |
TotalSize | The total capacity of the drive, in bytes |
VolumeName | The disk label (can be read and written) |
Table 2: All the properties of the Drive object.
The folder object represents an individual subdirectory. You can obtain a reference to such an object in different ways: by using the GetFolder or GetSpecialFolder methods of the root FileSystemObject object, through the RootFolder property of a Drive object, through the ParentFolder of the File object or another Folder object, or by iterating over the SubFolders collection of another Folder object. The folder object exposes a number of interesting properties, summarized in Table 3, but only the Attribute and Name properties can be written to. The most intriguing properties are probably the SubFolders and Files collections, which let you iterate through the subdirectories and files using an elegant and concise syntax, here is a short program to print all first-level directories on all drives together with their short 8.3 names:
Sub Main
Dim fso As Scripting.FileSystemObject
Dim dr As Scripting.Drive
Dim fld As Scripting.Folder
Set fso = New Scripting.FileSystemObject
Debug.Clear
On Error Resume Next
For Each dr In fso.Drives
If dr.IsReady Then
Debug.Print dr.RootFolder.Path
For Each fld In dr.RootFolder.SubFolders
Debug.Print " " & fld.Path & " [ " & fld.ShortName & " ] "
Next fld
End If
Next dr
End Sub
Table 3 summaries the properties of the folder and file objects.
Syntax | Applies To | Description |
---|---|---|
Attributes | Folder and File | The attributes of the file or the folder, as a combination of the following constants: 0-Normal, 1-ReadOnly, 2-Hidden, 4-System, 8-Volume, 16-Directory, 32-Archive, 64-Alias, 2048-Compressed |
DateCreated | Folder and File | Ceation date (a read-only date value). |
DateLastAccessed | Folder and File | The date of last access (a read-only date value.) |
DateLastModified | Folder and File | The date of last modification (a read-only date value.) |
Drive | Folder and File | The Drive object where the file or the folder is located. |
Files | Folder only | The collection of the contained File objects. |
IsRootFolder | Folder only | True if this is the root folder for its drive. |
Name | Folder and File | The name of the folder or file. |
ParentFolder | Folder and File | The parent folder object. |
Path | Folder and File | The path of the Folder or File (This is the default property) |
ShortName | Folder and File | The name of the object in 8.3 MS-DOS format. |
ShortPath | Folder and File | The path of the object in 8.3 MS-DOS format. |
Size | Folder and File | The size in bytes of a file object; the sum of the size of all contained files and subfolders for a Folder object. |
SubFolders | Folder only | The collection of all the subfolders contained in this folder, including system and hidden ones. |
Type | Folder and File | A string description of the object. For example fs.GetFolder(“C:\Recycled”).type returns “Recycle Bin”; for File objects, this value depends on their extensions (for example, “Text Document” for a TXT extension. |
Table 3 All the properties of Folder and File objects
The Folder object also exposes a few methods, summarized in Table 4. Note that you can often achieve similar results using appropriate methods of the main FSO object.
Syntax | Description | Applies To |
---|---|---|
Copy Destination [Overwrite] | Folder and File | Copy the current File or the Folder object to another path; this is similar to the FSO's CopyFolder and CopyFile methods, which are also able to copy multiple objects in one operation |
CreateTextFile(FileName,[Overwrite],[Unicode]) | Folder Only | Crates a text file in the current folder and returns the corresponding TextStream object. See the corresponding FSO's method for an explaination of the individual arguments |
Delete [Force] | Folder and File | Delete this file or folder object (with all its contained subfolders and files). Similar to FSO's DeleteFile and DeleteFolder methods. |
Move DistinationPath | Folder and File | Move this file or folder object to another path; similar to FSO's MoveFile and MoveFolder methods. |
OpenAsTextStream([IOModel],[Format]) As TextStream | File only | Open this File object as a text file and return the corresponding TextStream object. |
Table 4: All the methods of Folder and File objects.
You can also create a new Folder using the Add method applied to the SubFolders collection, as shown in the following recursive routine, which duplicates the directory structure of one drive onto another drive without also copying the contained files.
' Call this routine to initiate the copy process, the destination will be created if necessary.
Sub DuplicateDirTree(SourcePath As String, DestPath As String)
Dim fso As Scripting.FileSystemObject
Dim sourceFld As Scripting.Folder
Dim destFld As Scripting.Folder
Set fso = New Scripting.FileSystemObject
' The Source Folder Must Exist
Set sourceFld = fso.GetFolder(SourcePath)
' The Destination folder is created if necessary.
If fso.FolderExists(DestPath) Then
Set destFld = fso.GetFolder(DestPath)
Else
Set destFld = fso.CreateFolder(DestPath)
End If
' Jump to the recursive routine to do the copy.
DuplicateDirTreeSub sourceFld, destFld
End Sub
Sub DuplicateDirTreeSub(source As Scripting.Folder, destination As Scripting.Folder)
Dim sourceFld As Scripting.Folder
Dim destFld As Scripting.Folder
For Each sourceFld In source.SubFolders
' Copy this subfolder to the destination folder.
Set destFld = destination.SubFolders.Add(sourceFld.Name)
' Then repeat the process for all the subfolders of the folder just considered.
DuplicateDirTreeSub sourceFld, destFld
Next sourceFld
End Sub
The File object represents a single file on disk. You can obtain a reference to such an object in two ways:
Despite their different natures, File and Folder objects have many properties and methods in common, so I won't worry repeat the descriptions given in Tables 3 and 4.
A limitation of the FSO hierarchy is that you have no direct way to filter filenames using wildcards, as you can do with the Dir$ function. All you can do is iterate through the Files collection of a Folder object and test the file's name, extensions, or other attributes to see whether you are interested in it as shown in the following example.
' List all the DLL files in C:\WINDOWS\SYSTEM directory
Sub Main
Dim fso As Scripting.FileSystemObject
Dim fil As Scripting.File
Debug.Clear
Set fso = New Scripting.FileSystemObject
For Each fil In fso.GetSpecialFolder(SystemFolder).Files
If UCase$(fso.GetExtensionName(fil.Path)) = "DLL" Then
Debug.Print fil.Name
End If
Next fil
End Sub
The FileSystemObject hierarchy doesn't permit many operations on files. More specifically, while you can list their properties (including many properties that are beyond the current capabilities of native VB functions), you can open files only in text mode, as I explain in the next section.
The TextStream object represents a file opened in text mode. You can obtain a reference to such an object in the following ways:
The TextStream object exposes a number of methods for read-only properties, all of which are described in Table 5. The TextStream object does offer some new features in addition to the regular VB file commands – for example, the ability to keep track of the current line and column while reading from or writing to the text file. This feature is exploited in this reusable routine that scans all the TXT files in a directory for a search string and returns an array of the results (actually, an array of arrays) with all the files that contain that search string as well as the line number and the column number to indicate the position of the string within the file:
' Code Module
Sub Main
Debug.Clear
' An example use of the SearchTextFiles function
Dim v() As Variant
Dim i As Long
v() = SearchTextFiles("C:\Documents and Settings\dupree\My Documents", "TEST_FAILED")
For i = 1 To UBound(v)
Debug.Print v(i)(0)&", [" & v(i)(1) & ", " & v(i)(2) & "]"
Next i
End Sub
Function SearchTextFiles(Pathname As String, search As String) As Variant()
Dim fso As Scripting.FileSystemObject
Dim fldr As Scripting.Folder
Dim fil As Scripting.File
Dim ts As Scripting.TextStream
Dim pos As Long
Dim count As Long
ReDim result(50) As Variant
Set fso = New Scripting.FileSystemObject
Set fldr = fso.GetFolder(Pathname)
' Search for all the TXT files in the directory.
For Each fil In fldr.Files
If UCase$(fso.GetExtensionName(fil.Path)) = "TXT" Then
' Get the corresponding Text Stream object.
Set ts = fil.OpenAsTextStream(ForReading)
' Read it's contents, search the string, close it.
pos = InStr(1, ts.ReadAll, search)
ts.Close
If pos > 0 Then
' If the string has been found, reopen the file to determine string pos in terms of (line, col)
Set ts = fil.OpenAsTextStream(ForReading)
' Skip all the preceding characters to get to where the search string is.
ts.Skip pos - 1
' Fill the result array, maek room if necessary.
count = count + 1
If count > UBound(result) Then
ReDim Preserve result(UBound(result) + 50) As Variant
End If
' Each result item is a three element array.
result(count) = Array(fil.Path, ts.Line, ts.Column)
' Now we can close the text stream.
ts.Close
End If
End If
Next fil
' Resize the result array to indicate number of matches.
ReDim Preserve result(0 To count) As Variant
SearchTextFiles = result
End Function
Running this code I get the following output in the debug window:
C:\Documents and Settings\dupree\My Documents\Example_Text.txt, [1, 1]
C:\Documents and Settings\dupree\My Documents\Example_Text2.txt, [1, 20]
Which indicates that two files were found with the string “TEST_FAILED” both on the first line but one at the start and one 20 characters into the line.
Property or Method | Syntax | Description |
---|---|---|
Property | AtEndOfLine | True if the file pointer is at the end of the current line. |
Property | AtEndOfFile | True if the file pointer is at the end of file (similar to VB's EOF function) |
Method | Close | Closes the file (similar to VBs Close statement) |
Property | Column | Current column number |
Property | Line | Current line number |
Method | Read(Characters) | Reads a specified number of characters and returns a string (similar to VB's Input$ function) |
Method | ReadAll | Reads the entire file into a string (similar to VB's $Input function when used with the LOF function) |
Method | ReadLine | Reads the next line of text and returns a string (similar to VB's Line Input statement) |
Method | Skip Characters | Skips over a specified number of characters |
Method | SkipLine | Skips over a line of text |
Method | Write Text | Writes a string of characters, without a trailing Newline character (similar to Print# command with a trailing semicolon |
Method | WriteBlankLines Lines | Writes an indicated number of blank lines (similar to one or more Print# commands without any argument) |
Method | WriteLine [Text] | Writes a string of characters, with a trailing Newline character (similar to the Print# command without a trailing semicolon |
Table 5: All the properties and methods of the TextStream object.
So that completes this overview of the FileSystemObject object hierarchy provided by the Microsoft Scripting Library. The FileSystemObject provides modern, coherent and object-oriented way to work with Drives, Folders and Files which helps to make your code cleaner, more readable and easier to maintain.