The -x File Tests
Now you know how to open a filehandle for output, overwriting any existing file with the same name. Suppose you wanted to make sure that there wasn't a file by that name (to keep you from accidentally blowing away your spreadsheet data or that important birthday calendar). Perl uses -e $filevar to test for the existence of the file named by the scalar value in $filevar. If this file exists, the result is true; otherwise it is false. For example:
$name = "index.html"; if (-e $name) {
print "I see you already have a file named $name\n";
}
else {
print "Perhaps you'd like to make a file called $name\n";
}
The operand of the -e operator is really just any scalar expression that evaluates to some string, including a string literal. Here's an example that checks to see whether both index.html and index.cgi exist in the current directory:
if (-e "index.html" && -e "index.cgi") {
print "You have both styles of index files here.\n";
}
Other operators are defined as well. For example, -r $filevar returns true if the file named in $filevar exists and is readable. Similarly, -w $filevar tests whether it is writable. Here's an example that tests a user-specified filename for both readability and writability:
print "where? "; $filename = <STDIN>; chomp $filename; # toss pesky newline if (-r $filename && -w $filename) {
# file exists, and I can read and write it ... }
Many more file tests are available, some of which are not applicable to Perl for Win32. Table 10.1 lists some file tests and their meanings; for the whole list, see the perlfunc documentation.
| File Test | Meaning |
|---|---|
| -r | File or directory is readable |
| -w | File or directory is writable |
| -e | File or directory exists |
| -x | File is executable |
| -z | File exists and has zero size (directories are never empty) |
| -s | File or directory exists and has nonzero size (the value is the size in bytes) |
| -f | Entry is a plain file |
| -d | Entry is a directory |
| -t | isatty on the filehandle is true (that is, the filehandle is a character device)
|
| -T | File is text |
| -B | File is binary |
| -M | Modification age in days (C lang. time_t value) |
| -A | Access age in days (C lang. time_t value) |
| -C | Inode-modification age in days (C lang. time_t value) |
Most of these tests return a simple true-false condition. A few don't, so let's talk about them.
The -s operator does return true if the file is nonempty, but it's a particular kind of true. It's the length in bytes of the file, which evaluates as true for a nonzero number.
The age operators -M, -A, and -C (yes, they're uppercase) return the number of days since the file was last modified, accessed, or had its information changed.[] This age value is fractional with a resolution of one second: 36 hours is returned as 1.5 days. If you compare the age with a whole number (say three), you'll get only the files that were changed exactly that many days ago, not one second more or less. This means that you'll probably want a range comparison rather than an exact comparison to get files that are between three and four days old.[]
[8] The age is measured relative to the time the program started, as captured in C-library time into the
$^Tvariable. You can get negative numbers for these ages if the queried value refers to an event that happened after the program began.[9] Or, you might want to use the
intfunction.
These operators can operate on filehandles as well as filenames. Giving a filehandle for the operand is all it takes. So to test whether the file opened as SOMEFILE is executable, you can use:
if (-x SOMEFILE) {
# file open on SOMEFILE is executable }
If you leave the filename or filehandle parameter off (that is, if you specify just -r or -s), the default operand is the file named in the $_ variable (there it is again!). So, to test a list of filenames to see which ones are readable, it's as simple as:
foreach (@some_list_of_filenames) {
print "$_ is readable\n" if -r; # same as -r $_ }