1.13 Working With File Information

There are many ways in which Perl programs can communicate with the environment. We have already seen how we can read from and write to the terminal. We have also seen how we can read from and write to one or more files. We will see some other examples that will illustrate additional capabilities that are built into Perl for finding various useful information about a file.

In addition to reading and writing files, we can check to see the type of files that we have on our system. Perl provides us with several built-in predicates (functions that return true or false) to test file type or the access permissions associated with files. For example, there is a predicate -r that takes a filename as its argument and tells us if the file is readable. So,

(-r file_name )

when used as a condition in an if statement, will return true if file_name is a readable file. The name of the predicate is somewhat unusual in the sense that it starts with a minus (-) sign. Here are some other examples of such predicates that test file access permissions.

Predicate

The Test Performed

-B

The argument is a binary file

-d

The argument is a directory

-e

The argument is a file or directory that exists

-o

The argument is a file or directory owned by the user

-r

The argument is a file or directory that is readable by the Perl program

-T

The argument is a text file

-w

The argument is a file or directory that is writable by the Perl program

-x

The argument is a file or directory that is executable by the Perl program

The program given below takes a list of file names as command line arguments and prints, on the terminal, the contents of those files that are readable and textual.

Program 1.21

#!/usr/bin/perl
#Checks to see which files given as command line argument are text files and
#readable. If a file is a text file and readable, it prints its
#contents with each line numbered. Otherwise, it prints a message
#saying the file is unreadable and/or not textual.
#A possible command-line argument is *.

for ($i=0; $i <= $#ARGV; $i++){
    $filename = $ARGV[$i];
    print "File #$i: The current file is $filename\n";

    #if the file is a text file and is readable, then continue
    if ((-T $filename) && (-r $filename)){
        print "File #$i: $filename is a readable text file";
        print "\n" x 5;
        $linecount = 0; 

        open (READ, $filename);  #Print every line of the file to STDOUT
        while ($_ = ){ 
            print "$linecount\t$_";
            $linecount++;
        }
        print "\n" x 5;
        sleep (5);
    }

    else{ #if the file doesn't satisfy the text and readability condition
        print "File #$i: $filename is  unreadable and/or not a text file";
        print "\n" x 5;
        sleep (1);
    }
}

The program loops through the special variable @ARGV that contains all the command line arguments. In each iteration, it prints the file name. It then checks to see if the current file is a text file and is readable. This test is accomplished using

((-T $filename) && (-r $filename))

as the condition in the if statement. The conjoining operator is written by writing two ampersands together (&&). Note that the total conjoined or anded condition must be included inside parentheses although the individual conditions do not have to be. So, the following condition would have been acceptable.

(-T $filename && -r $filename)

Inside the if block of statements, the program prints a statement saying the file satisfies the test conditions and initializes a line counter. Then, it opens the current file for reading. It enters a while loop and prints every line of the file preceded by a line count. Once the whole file is printed, it waits for five seconds. This is done by the sleep command.

sleep (5);

sleep takes one argument that is interpreted as time in seconds

If the file is not textual and/or not readable, the program prints a message saying so.

We can call this program with * as the only command line argument if we want to look at all the readable text files in our current directory.