Previous Page
Next Page

10.11. Standard Input

Avoid using *STDIN, unless you really mean it.

The *STDIN stream doesn't always mean "...from the tty". And it never means "...from the files specified on the command line", unless you go out of your way to arrange for it to mean that:

    close *STDIN or croak "Can't close STDIN: $OS_ERROR";
    for my $filename (@ARGV) {
        open *STDIN, '<', $filename or croak "Can't open STDIN: $OS_ERROR";
        while (<STDIN>) {
            print substr($_,2);
        }
    }

which is, of course, so complicated and ugly that it constitutes its own punishment.

*STDIN is always attached to the zeroth file descriptor of your process. By default, that's bound to the terminal (if any), but you certainly can't rely on that default. For example, if data is being piped into your process, then *STDIN will be bound to file descriptor number 1 of the previous process in the pipeline. Or if your input to your process is being redirected from a file, then *STDIN will be connected to that file.

To cope with these diverse possibilities and the possibility that the user just typed the desired input file(s) on the command line without bothering with any redirection arrows, it's much safer to use Perl's vastly cleverer alternative: *ARGV. The *ARGV stream is connected to wherever *STDIN is connected, unless there are filenames on the command line, in which case it's connected to the concatenation of those files.

So you can allow your program to cope with interactive input, shell-level pipes, file redirections, and command-line file lists by writing this instead:


    while (my $line = <ARGV>) {
        print substr($line, 2);
    }

In fact, you use this magic filehandle all the time, possibly without even realizing it. *ARGV is the filehandle that's used when you don't specify any other:


    while (my $line = <>) {
        print substr($line, 2);
    }

It's perfectly good practice to use that shorterand more familiarform. This guideline is intended mainly to prevent you from unintentionally "fixing it": trying to be explicit, but then using the wrong filehandle:

    while (my $line = <STDIN>) {
        print substr($line, 2);
    }

    Previous Page
    Next Page