ksh:如何探测标准输入?

发布于 2024-07-15 01:58:46 字数 436 浏览 14 评论 0原文

我希望我的 ksh 脚本根据是否有东西通过 stdin 传入而具有不同的行为:

    (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)

检查 stdin 以查看它是否是终端 [ -t 0 ] 没有帮助,因为我的脚本是从其他脚本调用的。

如果 stdin 为“空”(第二种情况),则执行“cat <&0 >./tmp.dat”来检查 tmp.dat 的大小会挂起,等待来自 stdin 的 EOF。

如何检查 stdin 是否为“空”?!

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?!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伪心 2024-07-22 01:58:46

编辑:您正在 HP-UX 上运行

在 HP-UX 上测试了 [ -t 0 ] ,它似乎对我有用。 我使用了以下设置:

/tmp/x.ksh:

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

/tmp/y.ksh:

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

运行 /tmp/x.ksh 打印: terminal!

您能否在您的平台上确认上述内容,和/或提供更能反映您情况的替代测试设置? 您的脚本最终是由 cron 生成的吗?


编辑 2

如果绝望,并且 Perl 可用,请定义:

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'

编辑 3

请注意,如果您的输入来自 sort、ssh 等(所有这些程序都可以在您的脚本上生成并建立管道,然后在其上生成任何数据。)此外,使用严重的超时可能会严重影响您的脚本输入上没有任何内容(例如终端)。

如果潜在的大超时是一个问题,并且您可以影响脚本的调用方式,那么您可能需要强制调用者显式指示您的程序是否使用 stdin应该通过自定义选项或以标准 GNUtar 方式使用(例如 script [options [--]] FILE ...,其中 FILE 可以是文件名、表示标准输入的 - 或其组合,如果 - 作为参数传入,您的脚本将仅从标准输入读取。)

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.)

白馒头 2024-07-22 01:58:46

此策略适用于 bash,并且可能适用于 ksh。 投票“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

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
儭儭莪哋寶赑 2024-07-22 01:58:46

为什么不以更传统的方式解决这个问题,并使用命令行参数来指示数据将来自标准输入?

例如,考虑以下之间的区别:

<代码>echo foo | 猫-

echo foo > > /tmp/test.txt

cat /tmp/test.txt

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文