|
The -x File Tests
by Jeff Hunter, Sr. Database Administrator
The -x File Tests
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). If you were writing a shell script, you'd use something like-efilenameto test if the file exists. Similarly, Perl uses-e$filevarto 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.[4] 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-eoperator 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$filevarreturns true if the file named in$filevarexists and is readable. Similarly,-w$filevartests 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 ... }
Table 10.1: File Tests and Their Meanings File Test
Meaning
-rFile or directory is readable
-wFile or directory is writable
-xFile or directory is executable
-oFile or directory is owned by user
-RFile or directory is readable by real user, not effective user (differs from
-rfor setuid programs) -WFile or directory is writable by real user, not effective user (differs from
-wfor setuid programs) -XFile or directory is executable by real user, not effective user (differs from
-xfor setuid programs) -OFile or directory is owned by real user, not effective user (differs from
-ofor setuid programs) -eFile or directory exists
-zFile exists and has zero size (directories are never empty)
-sFile or directory exists and has nonzero size (the value is the size in bytes)
-fEntry is a plain file
-dEntry is a directory
-lEntry is a symlink
-SEntry is a socket
-pEntry is a named pipe (a "fifo")
-bEntry is a block-special file (like a mountable disk)
-cEntry is a character-special file (like an I/O device)
-uFile or directory is setuid
-gFile or directory is setgid
-kFile or directory has the sticky bit set
-t
isatty()on the filehandle is true -TFile is "text"
-BFile is "binary"
-MModification age in days
-AAccess age in days
-CInode-modification age in days
Most of these tests return a simple true-false condition. A few don't, so let's talk about them.
The
-soperator 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 inode changed.[5] (The inode contains all of the information about the file except for its contents: see thestatsystem call manpage for details.) 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 you'll probably want a range comparison[6] rather than an exact comparison to get files that are between three and four days old.[5] The age is measured relative to the time the program started, as captured in system time format in the
$^Tvariable. It's possible to get negative numbers for these ages if the queried value refers to an event that happened after the program began.[6] Or the
intoperator.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
SOMEFILEis executable, you can use:if (-x SOMEFILE) { # file open on SOMEFILE is executable }If you leave the filename or filehandle parameter off (that is, you have just
-ror-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 this:foreach (@some_list_of_filenames) { print "$_ is readable\n" if -r; # same as -r $_ }