in reply to Test for standard input

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

Replies are listed 'Best First'.
Re: Re: Test for standard input
by goldclaw (Scribe) on Oct 03, 2002 at 17:07 UTC
    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; } }

        You might consider looking at the problem a little differently. Frankly, your error, "No input found," makes very little sense. When called as simply

        $ grep
        the input, stdin, is still available to the program. What's missing is the pattern to search for in the input.

        Instead of going to all the trouble to test for a tty, you might find it's preferable to simply check to make sure there is at least one argument. If there is exactly one argument, it is the pattern and stdin is the input. If there are more than one then the subsequent ones are filenames of the files you wish to use for input. That way, it is only an error when no arguments are supplied. This is how grep(1) works so the behavior will be familiar even to users who have never used your program before.

        Also, you might want to add these to your test cases:

        $ grep < some_file $ cat | grep
        -sauoq
        "My two cents aren't worth a dime.";
        
        Sorry, I cannot resist. Your code is ummmm doing lots of things that I do not think are what you intend.
        $ARGS = @ARGV; if ( -t and $ARGS eq 0 ) { }
        The more idiomatic way of saying this is
        die "No input found\n" if ( -t and @ARGV == 0 );
        I would also like to point out that you are testing the wrong kind of equality in your code -- you used the string equality test ( eq ) instead of the numeric test ( == ). In this case it worked, but it will someday drive you nuts trying to hunt this kind of bug down.

        $names++, shift if $ARGV[0] eq "-l";
        If I have figured this out correctly, you are trying to parse some command line options. I would strongly recommend using Getopt::Long, a core module that does this job very well.

        I am assuming you really mean to shift the argument you just parsed out of @ARGV. Unfortunately, shift with no arguments assumes you mean @_, which is not @ARGV. Again, it likely works in this case, but I really doubt this is your intended affect.

        The same holds true for the next line.

        @ARGV = "-" unless @ARGV;
        This code will never be executed. I am assuming it is a hold-over from your previous problems. The 'if' at the top of the program makes certain that @ARGV has to have something in it.

        The assignment back to @ARGV is a little.... ugly IMHO. It took me several tries to figure out what it is doing. I would likely write this expression as

        exit 0 unless ( grep { -T or $_ eq "-" } @ARGV );
        but this is likely more a stylistic thing.

        Oh, good use of the -w flag. It appears, though, you forgot to use strict. It will seem a pain at first, but it will really help as your programs get longer and more complex.

        Mik
        mikfire