It's easier to write portable code if you manipulate filenames using the FileName class rather than using ordinary strings. TADS runs on several different operating systems with differing syntax rules for constructing file names and directory paths. The FileName class handles the different rules that apply on each system.
new FileName() - creates a FileName object representing the working
directory (e.g., '.' on Unix or Windows)
new FileName(str) - creates a FileName from a string 'str' giving a
file path in local filename syntax.
new FileName(path, name) - creates a FileName from a path and
a file name. 'path' and 'name' can each be a FileName
object or a string using local filename syntax. The
new object represents the combined path
new FileName(specialID) - creates a FileName from one of the special
file identifiers defined in file.h.
You can also use the fromUniversal() static method, which creates a FileName from a path in universal (URL-style) notation.
String conversions: using a FileName object in a context where a string is required (such as displaying it) automatically converts the object to a string giving the local file name path.
FileName + string => yields a new FileName object combining
the path given by FileName and the string naming a file,
in local naming conventions.
FileName + FileName => yields a new FileName object combining
the two names, treating the first as a directory path.
FileName == string (or !=) OR
FileName == FileName
Compares the FileName to the string or other filename path.
This does a superficial comparison of the path contents,
without attempting to correlate the path to the actual file
system layout. For example, it doesn't resolve symbolic
links on Unix or apply working directories to local paths.
FileName : Object
The new FileName object is in canonical form, meaning that any internal relative path elements (e.g., Unix "." and "..") are processed by combining them with adjacent elements as appropriate. For example, adding ".." to the Unix path "a/b/c" yields "a/b".
If 'createParents' is specified, it's a true or nil value specifying whether or not to create intermediate parent directories. The default is nil if it's omitted. If it's true, and 'dirname' contains multiple path elements, any parents of the named directory that don't already exist will be created as well. For example, on Linux, if dirname is '/a/b/c', and directory '/a' exists but not '/a/b', the routine will first create '/a/b' and then create '/a/b/c'.
If it's not possible to convert the filename into an absolute path, returns nil.
'asLink' has the same meaning as in getFileType(), and has no effect at all unless the file named is a symbolic link.
The file safety settings must allow read access to the file.
If the file is a symbolic link, the method's behavior depends on 'asLink'. A symbolic link is a special type of file supported on some operating systems that serves as a pointer or proxy for another file. If the file is a link, and 'asLink' is omitted or nil, the method returns information on the target of the link; this is the default because symbolic links in generally act as transparent proxies for their targets, so for most purposes a caller should be interested in the target file's metadata. However, a symbolic link also has a separate identity of its own as a link, so callers might sometimes be interested in the metadata for the link rather than its target. To get information on the link itself, set 'asLink' to true. 'asLink' has no effect for ordinary non-link files, and also has no effect for "hard" links on systems that support those as well.
Most of the FileTypeXxx bits are mutually exclusive, but it's possible that more than one bit will be set, so test using '&' (e.g., (f.getFileType() & FileTypeDir)).
The file safety settings must allow read access to the file.
Note that a Windows path can start with a drive letter without being absolute, as in "C:path\file" (that's relative to the working folder on the C: drive), and can start with a backslash without being absolute, as in "\path\file" (that's relative to the working drive letter). Similar subtleties might apply to other systems; this routine figures it out using local conventions.
The file safety settings must allow read access to the directory's contents.
On systems where the file system has special directory entries for relative links, such as "." and ".." on Windows and Unix-likes, the listing that this method returns will include entries for those relative links. Be careful with these when performing recursive directory traversals, since recursing into "." or ".." would cause an infinite loop. You can test an entry in the returned list to see if it's one of these special links by calling its getFileInfo() method, and testing the specialLink property of the returned information object. Not that if you're performing a recursive directory traversal, it might be easier to use forEachFile() with the 'recurse' argument flag set to true.
If 'removeContents' is provided, it's a true or nil value specifying whether or not to delete the contents of the directory before deleting the directory itself. If this is true, and the directory contains any files or subdirectories, the routine will attempt to delete those contents before deleting the directory itself. Any subdirectories will be recursively emptied and removed. For obvious reasons, use caution when using this flag. If any of the contents can't be deleted, the function will stop and throw an error. Note that if this occurs, the function might have successfully deleted some of the contents of the directory before encountering the error; those deletions won't be undone.
If 'removeContents' is omitted or nil, and the directory isn't already empty, the method simply returns nil (indicating failure) without deleting anything. This is the default because it helps avoid accidentally deleting contents that the application didn't explicitly choose to remove. (Special system files that are always present, such as "." and ".." on Unix, don't count when determining if the directory is empty.)