Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to find a way of testing for the existence of standard input in a perl program : I've done a lot of searching but so far can't find the answer. I've seen some sample code from Randal where he made a perl grep program :
#!/bin/perl -w $names++, shift if $ARGV[0] eq "-l"; $search = shift; $showname = @ARGV > 1; @ARGV = "-" unless @ARGV; @ARGV = grep { -T or $_ eq "-" } @ARGV; exit 0 unless @ARGV; while (<>) { next unless /$search/o; if ($names) { print "$ARGV\n"; close ARGV; } else { print "$ARGV: " if $showname; print; } }
I'll call the above program "grep". The program works fine for either of these 2 methods :
1. grep pattern /tmp/file 2. cat /tmp/file | grep pattern
But when I run "grep" by itself, it waits for STDIN. I want the program to print out a "usage message" if the user just runs "grep". How would I do this ?

Replies are listed 'Best First'.
Re: Test for standard input
by zigdon (Deacon) on Oct 03, 2002 at 16:36 UTC

    testing STDIN with -t might help - see perlfaq - How do I know if I'm running interactively or not?.

    Sorry, I think I misunderstood the FAQ here - -t doesn't seem to work as I thought.

    update: After some more reading, I think it can't be done. it's easy to differentiate between these two

    perl -ne 'print' /path/to/file cat /path/to/file | perl -ne 'print'
    by looking at $ARGV, but I'm not sure perl can even know the difference between these two
    cat /path/to/file | perl -ne 'print' perl -ne 'print'

    -- Dan

      I think you were on to something the first time. -t will check if the filehandle is hooked up to a tty, which is the case if you run it from the command line, without a pipe. So you can check with -t and check the arguments, and give an appropriate error message.

      Now, if the program is run through a fork/exec, or another non-interactive facility, you can't really know until the parent process closes its stdout. The parent might wait for 5 years before it decides to print something out, so any check based on testing for actual input would be wrong.

      Goldclaw

        Thanks alot ! The -t flag worked. Here's the new code :
        #!/bin/perl -w $ARGS = @ARGV; if (-t and $ARGS eq 0 ) { print "No input found\n"; exit 1; } $names++, shift if $ARGV[0] eq "-l"; $search = shift; $showname = @ARGV > 1; @ARGV = "-" unless @ARGV; @ARGV = grep { -T or $_ eq "-" } @ARGV; exit 0 unless @ARGV; while (<>) { next unless /$search/o; if ($names) { print "$ARGV\n"; close ARGV; } else { print "$ARGV: " if $showname; print; } }