next up previous contents
Next: File Functions Up: Files Input Previous: Using the Diamond Operator

File Test Operators

Perl has many operators that you can use to test different aspects of a file. For example, you can use the -e operator to ensure that a file exists before deleting it. Or, you can check that a file can be written to before appending to it. By checking the feasibility of the impending file operation, you can reduce the number of errors that your program will encounter.

A complete list of the operators used to test files is given in Table 9.1


   
Table 9.1: File Operands
Operator Description
-A OPERAND Returns the access age of OPERAND when the program started.
-bOPERAND Tests if OPERAND is a block device.
-BOPERAND Tests if OPERAND is a binary file. If OPERAND is a file handle,
  then the current buffer is examined, instead of the file itself.
-c OPERAND Tests if OPERAND is a character device.
-COPERAND Returns the inode change age of OPERAND when the program started.
-dOPERAND Tests if OPERAND is a directory.
-eOPERAND Tests if OPERAND exists.
-fOPERAND Tests if OPERAND is a regular file as opposed to a directory,
  symbolic link or other type of file.
-g OPERAND Tests if OPERAND has the setgid bit set.
-kOPERAND Tests if OPERAND has the sticky bit set.
-lOPERAND Tests if OPERAND is a symbolic link. Under DOS,
  this operator always will return false.
-M OPERAND Returns the age of OPERAND in days when the program started.
-oOPERAND Tests if OPERAND is owned by the effective uid.
  Under DOS, it always returns true.
-OOPERAND Tests if OPERAND is owned by the read uid/gid.
  Under DOS, it always returns true.
-pOPERAND Tests if OPERAND is a named pipe.
-rOPERAND Tests if OPERAND can be read from.
-ROPERAND Tests if OPERAND can be read from by the real uid/gid.
  Under DOS, it is identical to -r.
-sOPERAND Returns the size of OPERAND in bytes.
  Therefore, it returns true if OPERAND is non-zero.
-SOPERAND Tests if OPERAND is a socket.
-tOPERAND Tests if OPERAND is opened to a tty.
-TOPERAND Tests if OPERAND is a text file. If OPERAND is a file handle,
  then the current buffer is examined, instead of the file itself.
-uOPERAND Tests if OPERAND has the setuid bit set.
-w OPERAND Tests if OPERAND can be written to.
-W OPERAND Tests if OPERAND can be written to by the real uid/gid.
  Under DOS, it is identical to -w.
-xOPERAND Tests if OPERAND can be executed.
-XOPERAND Tests if OPERAND can be executed by the real uid/gid.
  Under DOS, it is identical to -x.
-zOPERAND Tests if OPERAND size is zero.

Note If the OPERAND is not specified in the file test, the $ variable will be used instead.

The operand used by the file tests can be either a file handle or a file name. The file tests work by internally calling the operating system to determine information about the file in question. The operators will evaluate to true if the test succeeds and false if it does not.

If you need to perform two or more tests on the same file, you use the special underscore (_) file handle. This tells Perl to use the file information for the last system query and saves time. However, the underscore file handle does have some caveats. It does not work with the -t operator. In addition, the lstat() function and -l test will leave the system buffer filled with information about a symbolic link, not a real file.

The -T and -B file tests will examine the first block or so of the file. If more than 10 percent of the bytes are non-characters or if a null byte is encountered, then the file is considered a binary file. Binary files are normally data files, as opposed to text or human-readable files. If you need to work with binary files, be sure to use the binmode() file function, which is described in the section, "Example: Binary Files," later in this chapter.

Using File Tests

For our first example with file tests, let's examine a list of files from the command line and determine if each is a regular file or a special file test.pl.

foreach (@ARGV) {

                print;

                print((-f) ? " -REGULAR\n" : " -SPECIAL\n")

               }

When this program is run using the following command line:

 
perl -w 09lst01.pl \perl5 perl.exe \windows

the following is displayed:

09lst01.pl -REGULAR

\perl5 -SPECIAL

perl.exe -REGULAR

\windows -SPECIAL

Each of the directories listed on the command line were recognized as special files. If you want to ignore all special files in the command line, you do so like this test2.pl:

foreach (@ARGV) {

    next unless -f;    # ignore all non-normal files.

    print;

    print((-f) ? " -REGULAR\n" : " -SPECIAL\n")

}

When this program is run using the following command line:

perl -w 09lst01.pl \perl perl.exe \windows}

the following is displayed:

09lst01.pl -REGULAR
perl.exe -REGULAR

Notice that only the regular file names are displayed. The two directories on the command line were ignored.

As mentioned above, you can use the underscore file handle to make two tests in a row on the same file so that your program can execute faster and use less system resources. This could be important if your application is time critical or makes many repeated tests on a large number of files size.pl.

foreach (@ARGV) {

    next unless -f;

    $fileSize = -s _;

    print("$_ is $fileSize bytes long.\n");

}

When this program is run using the following command line:

perl -w 09lst06.pl \perl5 09lst01.pl \windows perl.exe

the following is displayed:

09lst01.pl is 36 bytes long.
perl.exe is 61952 bytes long.


next up previous contents
Next: File Functions Up: Files Input Previous: Using the Diamond Operator
dave@cs.cf.ac.uk