EDJ
EDJ

Reputation: 485

In Perl, how do I determine if there's a standard input present?

I've got a script that grabs standard input:

&process_input

sub process_input {
    while(<STDIN>) {
       $log_data .= $_;
    }
}

When I run the script:

myscript.pl -param1=a -param2=b

I get stuck in this subroutine. Everything runs OK if I do:

echo "" | myscript.pl -param1=a -param2=b

How do I determine if I even have a standard input?

I would have thought that while(<STDIN>) would return false and not run, but I'm guessing it's actually waiting for you to type something in that why it's 'stuck'.

Upvotes: 6

Views: 8049

Answers (4)

OregonTrail
OregonTrail

Reputation: 9049

Your program will continue when the user types Ctrl + D, the end-of-file character.

Upvotes: 0

ikegami
ikegami

Reputation: 386501

That's normal. Standard usage for Unix tools is to use STDIN if no input file is given as an argument. Try cat, less, grep, etc. It's up to the caller to provide input, if only

tool < /dev/null

I strongly advise against trying to determine if "input" is available as it will introduce problems no matter how you achieve this. Specifically, avoid -t since it's problematic to fake a terminal when needed. Instead, rely on a more conventional interface.

If you want to make it possible to pass no input to your tool, it's weird that you'd be using STDIN in the first place. One would normally use an optional argument.

tool --foo file
tool --foo <( echo "" )

Another option would be to request that the user tells you when there is no input.

tool --batch

In order to help you with the design problems of your interface, it would really help to know what your tool does.

Upvotes: 1

JSBձոգչ
JSBձոգչ

Reputation: 41388

The statement <STDIN> does not return until you press Enter on the console. If you want to get around this, I believe that you can use IO::Handle to wrap STDIN, and call $stdin->blocking(0) to enable non-blocking I/O.

Upvotes: 2

MvanGeest
MvanGeest

Reputation: 9661

You want to check where your STDIN (STanDard INput) is coming from: another application or a terminal. In your case, it's the second option, causing a read operation to stall the process until the user inputs something. For a solution, see How can I tell if STDIN is connected to a terminal in Perl?.

if (-t STDIN) {
    # input attached to terminal and will probably ask user
} else {
    # input from other process
}

There's also IO::Interactive that might do better/more reliable checking.

Upvotes: 20

Related Questions