This section explores functions that deal with inspecting and manipulating entire files, rather than the contents of those files. Some of these functions have a dual purpose, acting on both files and directories. In each case, the function accepts at least one argument that identifies a file or directory. The following things are true about arguments that identify files or directories:
If the path is not present, the current directory - as returned by CurDir - is used.
The system representation and the URL notation are both allowed. For example, "C:\tmp\foo.txt" and "file:///c:/tmp/foo.txt" refer to the same file.
Unless it is explicitly stated, a single file or directory must be uniquely identified. The only function that accepts a file specification is Dir, which returns a listing of files matching the file specification.
Each file and directory has attributes (see Table 3 ). Each attribute represents a single bit in a number, allowing each item in a path to have multiple attributes set at the same time. Some attributes have been deprecated to be more system dependent. Not all systems support hidden or system files, for example. Use GetAttr to return the attributes.
Deprecated | Attribute | Description |
---|---|---|
No |
| Normal; no bits set |
No | 1 | Read-Only |
Yes | 2 | Hidden |
Yes | 4 | System |
No | 8 | Volume |
No | 16 | Directory |
No | 32 | Archive bit (file changed since last backed up) |
Compatibility | Visual Basic supports all attributes in Table 3 as well as an Alias attribute. |
The function in Listing 4 accepts an attribute from the GetAttr function and returns an easy-to-understand string. If no bits are set, the attributes indicate a normal file.
REM uses bitwise comparison to read the attributes Function FileAttributeString(x As Integer) As String Dim s As String If (x = 0) Then s = "Normal" Else If (x AND 16) <> 0 Then s = "Directory" 'Directory bit 00010000 set If (x AND 1) <> 0 Then s = s & " Read-Only" 'read-only bit 00000001 set If (x AND 2) <> 0 Then s = s & " Hidden" 'Deprecated If (x AND 4) <> 0 Then s = s & " System" 'Deprecated If (x AND 8) <> 0 Then s = s & " Volume" 'Volume bit 00001000 set If (x AND 32) <> 0 Then s = s & " Archive" 'Archive bit 00100000 set End If FileAttributeString = s End Function
Note | Listing 4 performs bit operations (explained later) to determine which attributes are set. |
Use the GetAttr function to get the attributes of a file, and use SetAttr to set the attributes. The first argument to the function SetAttr is the name of the file-relative or absolute-and the second argument is a number representing the attributes to set or clear. In other words, after calling SetAttr(name, n), the function GetAttr( name ) should return the integer n. For example, calling SetAttr with the attribute set to 32 sets the archive bit and clears all the others so GetAttr returns 32. To set more than one bit at the same time, use the OR operator to combine attributes. Use SetAttr (fileName, 1 OR 32) to set both the archive bit and the read-only bit. SetAttr works on directories as well as files.
Note | Although the supported attributes have been modified to become less operating-system specific, they still favor Windows. On Unix-based operating systems such as Linux and Sun, setting attributes affects the user , group , and world settings. Setting the attribute to 0 (not read-only) corresponds to "rwxrwxrwx". Setting the attribute to 1 (read-only) corresponds to "r r r". |
Use the FileLen function to determine the length of a file. The return value is a long. The function in Listing 5 obtains the file length and then creates a pretty string to display the length. The file length is returned in bytes-K, MB, G, or T-depending on the length. This produces a more easily understood result than a simple number.
Function PrettyFileLen(path$) As String PrettyFileLen = nPrettyFileLen(FileLen(path)) End Function Function nPrettyFileLen(ByVal n As Double) As String Dim i As Integer 'Count number of iterations Dim v() As Variant 'Holds abbreviations for Kilobytes, Megabytes, ... v() = Array("bytes", "K", "MB", "G", "T") 'Abbreviations REM Every time that the number is reduced by 1 kilobyte, REM the counter is increased by 1. REM Do not decrease the size to less than 1 kilobyte. REM Do not increase the counter by more than the size of the array. Do While n > 1024 AND i+1 < UBound(v()) n = Fix(n / 1024) 'Truncate after the division i = i + 1 'Started at i=0 (bytes) increment to next abbreviation Loop nPrettyFileLen = CStr(n) & v(i) End Function
Use the FileExist function to determine if a file or directory exists. Use FileDateTime to return a string with the date and time that a file was created or last modified. The returned string is in a system-dependent format. On my computer, the format is "MM/DD/YYYY HH:MM:SS". The returned string can be passed directly to the function CDate. The GetFileInfo macro in Lisiting 6 uses all of the file and directory inspection functions to return information in an easy-to-read format. Also see Figure 2 .
Function GetFileInfo(path) As String Dim s As String Dim iAttr As Integer s = "The path """ & path & """" If Not FileExists(path) Then GetFileInfo = s & " does not exist" Exit Function End If s = s & " exists" & CHR$(10) s = s & "Date and Time = " & FileDateTime(path) & CHR$(10) iAttr = GetAttr(path) REM The length of a directory is always zero If (iAttr AND 16) = 0 Then s = s & "File length = " & PrettyFileLen(path) & CHR$(10) End If s = s & "Attributes = " & FileAttributeString(iAttr) & CHR$(10) GetFileInfo = s End Function
Use the Kill statement to delete a file from the disk. A run-time error occurs if the file does not exist.
Kill("C:\temp\BadFile.txt")
Use the FileCopy function to copy files. The first argument is the file to copy and the second argument is the destination file. See Table 4 . The FileCopy function is able to recursively copy entire directories, but it can't handle file specifications. Surprisingly, if the first argument is a file, the second argument must also be a file-I expected that I could copy a file to a directory with FileCopy("C:\auto.bat", "C:\bak\").
Valid | Source | Destination | Comment |
---|---|---|---|
Yes | File | File | Copy the file. The names do not have to be the same. |
Yes | Directory | Directory | Recursively copy all files and directories contained in one directory to another directory. |
No | file spec | File specifications (wildcards, for example, *.*) are not allowed. | |
No | File | Directory | If the source is a file, the destination must also be a file. |
FileCopy("C:\auto.bat", "C:\auto.bak") 'Copy file FileCopy("C:\auto.bat", "C:\tmp\auto.bat") 'Copy file FileCopy("C:\logs", "C:\bak") 'Copy directory
Warning | Do not recursively copy a directory into itself-this creates an infinite loop. For example, FileCopy("C:Vogs", "C:\logs\bak") will never finish because the "bak" subdirectory immeditately becomes part of the contents of "logs"; which then has to be copied as well. Bad idea. |
Use the Name statement to rename a file or directory. This statement has an unusual syntax: It places the keyword As between the source and destination names.
Name "C:\Joe.txt" As "C:\bill.txt" 'Rename a file Name "C:\logs" As "C:\oldlogs" 'Rename a directory Name "C:\Joe.txt" As "C:\tmp\joe.txt" 'Move the file to the tmp directory Name "C:\logs" As "C:\bak\logs" 'Move the logs directory
Tip | A common power-user trick is to use the Name command to move a file or directory from one location to another. |