How can I check (peek) STDIN for piped data in Perl without using select?

拜拜、爱过 提交于 2019-12-03 12:04:43

Perl comes with the -t file-test operator, which tells you if a particular filehandle is open to a TTY. So, you should be able to do this:

if ( -t STDIN and not @ARGV ) {
    # We're talking to a terminal, but have no command line arguments.
    # Complain loudly.
}
else {
    # We're either reading from a file or pipe, or we have arguments in
    # @ARGV to process.
}

A quick test reveals this working fine on Windows with Perl 5.10.0, and Linux with Perl 5.8.8, so it should be portable across the most common Perl environments.

As others have mentioned, select would not be a reliable choice as there may be times when you're reading from a process, but that process hasn't started writing yet.

All the best,

Paul

use POSIX 'isatty';
if ( ! @ARGV && isatty(*STDIN) ) {
    die "usage: ...";
}

See: http://www.opengroup.org/onlinepubs/009695399/functions/isatty.html

Note that select wouldn't be much help anyway, since it would produce false results if the piped info wasn't ready yet. Example:

seq 100000|grep 99999|perl -we'$rin="";vec($rin,fileno(STDIN),1)=1;print 0+select($rin,"","",.01)'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!