Home arrow Perl Programming arrow File Tests in Perl

File Tests in Perl

In this article, you will learn how to find out useful information about files in Perl. It is excerpted from chapter 11 of the book Learning Perl, Fourth Edition, written by Randal L. Schwartz, Tom Phoenix and brian d foy (O'Reilly; ISBN: 0596101058). Copyright © 2006 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

  1. File Tests in Perl
  2. File Test Operators
  3. The stat and lstat Functions
  4. The localtime Function
  5. Bitwise Operators
  6. Using the Special Underscore Filehandle
By: O'Reilly Media
Rating: starstarstarstarstar / 22
May 10, 2007

print this article



Earlier, we showed how to open a filehandle for output. Normally, that will create a new file, wiping out any existing file with the same name. Perhaps you want to check that there isnít a file by that name. Perhaps you need to know how old a given file is. Or perhaps you want to go through a list of files to find which ones are larger than a certain number of bytes and not accessed for a certain amount of time. Perl has a complete set of tests you can use to find information about files.

File Test Operators

Before we start a program that creates a new file, letís make sure the file doesnít already exist so that we donít accidentally overwrite a vital spreadsheet data file or that important birthday calendar. For this, we use the -e file test, testing a filename for existence:

  die "Oops! A file called '$filename' already exists.\n"
    if -e $filename;

We didnít include$!in thisdiemessage since weíre not reporting that the system refused a request in this case. Hereís an example of checking if a file is being kept up to date. In this case, weíre testing an already opened filehandle instead of a string file name. Letís say that our programís configuration file should be updated every week or two. (Maybe itís checking for computer viruses.) If the file hasnít been modified in the past 28 days, then something is wrong:

  warn "Config file is looking pretty old!\n"
    if -M CONFIG > 28;

The third example is more complex. Letís say disk space is filling up; rather than buy more disks, weíve decided to move any large, useless files to the backup tapes. So letís go through our list of files* to see which of them are larger than 100 KB. But even if a file is large, we shouldnít move it to the backup tapes unless it hasnít been accessed in the last 90 days (so we know itís not used too often):Ü

  my @original_files = qw/ fred barney betty wilma pebbles dino bamm-bamm /;
  my @big_old_files; # The ones we want to put on backup tapes
  foreach my $filename (@original_files) {
    push @big_old_files, $filename
      if -s $filename > 100_000 and -A $filename > 90;

This is the first time that youíve seen it, so maybe you noticed that the control variable of theforeachloop is amyvariable. That declares it to have the scope of the loop, so this example should work underuse strict. Without themykeyword, this would be using the global$filename.

The file tests look like a hyphen and a letter, which is the name of the test, followed by a filename or a filehandle to test. Many of them return a true/false value, but several give something more interesting. See Table 11-1 for the complete list and read the following discussion to learn more about the special cases.

Table 11-1.  File tests and their meanings

File test Meaning
-r File or directory is readable by this (effective) user or group
-w File or directory is writable by this (effective) user or group
-x File or directory is executable by this (effective) user or group
-o File or directory is owned by this (effective) user
-R File or directory is readable by this real user or group
-W File or directory is writable by this real user or group
-X File or directory is executable by this real user or group
-O File or directory is owned by this real user
-e File or directory name exists
-z File exists and has zero size (always false for directories)
-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
-l Entry is a symbolic link
-S Entry is a socket

File Test Operators

Table 11-1.  File tests and their meanings (continued)

File test Meaning
-p Entry is a named pipe (a ďfifoĒ)
-b Entry is a block-special file (like a mountable disk)
-c Entry is a character-special file (like an I/O device)
-u File or directory is setuid
-g File or directory is setgid
-k File or directory has the sticky bit set
-t The filehandle is a TTY (as reported by theisatty()system function; filenames canít be tested by this test)
-T File looks like a ďtextĒ file
-B File looks like a ďbinaryĒ file
-M Modification age (measured in days)
-A Access age (measured in days)
-C Inode-modification age (measured in days) 

The tests -r, -w,-x, and-otell if the given attribute is true for the effective user or group ID,* which essentially refers to the person who is in charge of running the program.Ü These tests look at the permission bits on the file to see what is permitted. If your system uses Access Control Lists (ACLs), the tests will use those as well. These tests generally tell if the system would try to permit something, but it doesnít mean that it really would be possible. For example,-wmay be true for a file on a CD-ROM, though you canít write to it, or-xmay be true on an empty file, which canít truly be executed.

The-stest does return true if the file is non-empty, but itís a special kind of true. Itís the length of the file, measured in bytes, which evaluates as true for a nonzero number.

A Unix filesystemá has seven types of items, represented by the seven file tests-f,-d,-l,-S,-p,-b, and-c. Any item should be one of those. If you have a symbolic link pointing to a file, that will report true for-fand-l. So if you want to know whether something is a symbolic link, you should generally test that first. (Youíll learn more about symbolic links in Chapter 12.)

The age tests,-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.* (The inode contains all of the information about the file except for its contents. See thestatsystem call manpage or a good book on Unix internals for details.) This age value is a full floating-point number, so you might get a value of2.00001if a file were modified two days and one second ago. These ďdaysĒ arenít necessarily the same as a human would count. For example, if itís 1:30 A.M. when you check a file modified at about an hour before midnight, the value of-Mfor this file would be around0.1, even though it was modified ďyesterday.Ē

When checking the age of a file, you might get a negative value like-1.2, which means that the fileís last access timestamp is set at about thirty hours in the future. The zero point on this timescale is the moment your program started running,Ü so that value might mean a long-running program was looking at a file that had just been accessed. Or a timestamp could be set (accidentally or intentionally) to a time in the future.

The tests-Tand-Bdetermine if a file is text or binary. But people who know a lot about filesystems know thereís no bit (at least in Unix-like operating systems) to indicate that a file is a binary or text file, so how can Perl tell? The answer is that Perl cheats: it opens the file, looks at the first few thousand bytes, and makes an educated guess. If it sees a lot of null bytes, unusual control characters, and bytes with the high bit set, then that looks like a binary file. If thereís not much weird stuff, then it looks like text. It sometimes guesses wrong. If a text file has a lot of Swedish or French words (which may have characters represented with the high bit set, as some ISO-8859-something variant, or perhaps even a Unicode version), it may fool Perl into declaring it binary. So itís not perfect, but if you need to separate your source code from compiled files, or HTML files from PNGs, these tests should do the trick.

Youíd think that-Tand-Bwould always disagree since a text file isnít a binary and vice versa, but there are two special cases where theyíre in complete agreement. If the file doesnít exist, or canít be read, both are false since itís neither a text file nor a binary. Alternatively, if the file is empty, itís an empty text file and an empty binary file at the same time, so theyíre both true.

The-tfile test returns true if the given filehandle is a TTYóif itís interactive because itís not a simple file or pipe. When-t STDINreturns true, it generally means that you can interactively ask the user questions. If itís false, your program is probably getting input from a file or pipe, rather than a keyboard.

>>> More Perl Programming Articles          >>> More By O'Reilly Media

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort


- Perl Turns 25
- Lists and Arguments in Perl
- Variables and Arguments in Perl
- Understanding Scope and Packages in Perl
- Arguments and Return Values in Perl
- Invoking Perl Subroutines and Functions
- Subroutines and Functions in Perl
- Perl Basics: Writing and Debugging Programs
- Structure and Statements in Perl
- First Steps in Perl
- Completing Regular Expression Basics
- Modifiers, Boundaries, and Regular Expressio...
- Quantifiers and Other Regular Expression Bas...
- Parsing and Regular Expression Basics
- Hash Functions

Developer Shed Affiliates


Dev Shed Tutorial Topics: