ksh: how to probe stdin?

非 Y 不嫁゛ 提交于 2020-01-01 06:15:31

问题


I want my ksh script to have different behaviors depending on whether there is something incoming through stdin or not:

    (1) cat file.txt | ./script.ksh  (then do "cat <&0 >./tmp.dat" and process tmp.dat)
vs. (2) ./script.ksh (then process $1 which must be a readable regular file)

Checking for stdin to see if it is a terminal[ -t 0 ] is not helpful, because my script is called from an other script.

Doing "cat <&0 >./tmp.dat" to check tmp.dat's size hangs up waiting for an EOF from stdin if stdin is "empty" (2nd case).

How to just check if stdin is "empty" or not?!


回答1:


EDIT: You are running on HP-UX

Tested [ -t 0 ] on HP-UX and it appears to be working for me. I have used the following setup:

/tmp/x.ksh:

#!/bin/ksh
/tmp/y.ksh

/tmp/y.ksh:

#!/bin/ksh
test -t 0 && echo "terminal!"

Running /tmp/x.ksh prints: terminal!

Could you confirm the above on your platform, and/or provide an alternate test setup more closely reflecting your situation? Is your script ultimately spawned by cron?


EDIT 2

If desperate, and if Perl is available, define:

stdin_ready() {
  TIMEOUT=$1; shift
  perl -e '
    my $rin = "";
    vec($rin,fileno(STDIN),1) = 1;
    select($rout=$rin, undef, undef, '$TIMEOUT') < 1 && exit 1;
  '
}

stdin_ready 1 || 'stdin not ready in 1 second, assuming terminal'

EDIT 3

Please note that the timeout may need to be significant if your input comes from sort, ssh etc. (all these programs can spawn and establish the pipe with your script seconds or minutes before producing any data over it.) Also, using a hefty timeout may dramatically penalize your script when there is nothing on the input to begin with (e.g. terminal.)

If potentially large timeouts are a problem, and if you can influence the way in which your script is called, then you may want to force the callers to explicitly instruct your program whether stdin should be used, via a custom option or in the standard GNU or tar manner (e.g. script [options [--]] FILE ..., where FILE can be a file name, a - to denote standard input, or a combination thereof, and your script would only read from standard input if - were passed in as a parameter.)




回答2:


This strategy works for bash, and would likely work for ksh. Poll 'tty':

#!/bin/bash
set -a

if [ "$( tty )" == 'not a tty' ]
then
    STDIN_DATA_PRESENT=1
else
    STDIN_DATA_PRESENT=0
fi

if [ ${STDIN_DATA_PRESENT} -eq 1 ]
then
    echo "Input was found."
else
    echo "Input was not found."
fi



回答3:


Why not solve this in a more traditional way, and use the command line argument to indicate that the data will be coming from stdin?

For an example, consider the difference between:

echo foo | cat -

and

echo foo > /tmp/test.txt

cat /tmp/test.txt



来源:https://stackoverflow.com/questions/635361/ksh-how-to-probe-stdin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!