如何检查 stdin 是来自终端还是 shell 脚本中的管道?

发布于 2024-08-24 23:52:03 字数 272 浏览 6 评论 0 原文

我正在编写一个 POSIX shell 脚本,它可能会也可能不会从 stdin 接收输入,如 foo.sh foo.sh foo.sh foo.sh foo.sh foo.sh foo.sh < test.txt,非交互方式。

如何检查标准输入上是否有任何内容,以避免在读取 -r 行...时暂停

I am writing a POSIX shell script that may or may not receive input from stdin as in foo.sh < test.txt, non-interactively.

How do I check whether there is anything on stdin, to avoid halting on while read -r line...?

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

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

发布评论

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

评论(4

她比我温柔 2024-08-31 23:52:03

如果我的问题答对了,您可以尝试以下操作:

#!/bin/sh
if [ -t 0 ]; then
    echo running interactivelly
else
    while read -r line ; do
        echo $line
    done
fi

If I get the question right, you may try the following:

#!/bin/sh
if [ -t 0 ]; then
    echo running interactivelly
else
    while read -r line ; do
        echo $line
    done
fi
戈亓 2024-08-31 23:52:03

从字面上回答这个问题(但不是你真正想要的):read -t 0

超时,零秒。

  1. 这是一个竞争条件,取决于左侧何时准备好提供数据。您可以指定 -t 5 但在抖动系统上即使这样也是有问题的。
  2. read -t 在 SUSv3 中未标准化。它位于 BSD sh、bash、zsh 中。它不是用 ksh 或 dash 表示的。

所以你不能只使用 #!/bin/sh 并期望得到这个。

基本问题是,即使现在标准输入上没有任何内容,也不意味着很快就会有。调用程序通常会使标准输入连接到终端/其他设备,因此无法知道需要什么。

因此,要从字面上回答您的问题,您可以这样做,但实际上您的选择是:

  1. 测试 stdin 是否是 tty: [ -t 0 ]
  2. 使用 argv 来控制行为

To answer the question literally (but not what you actually want): read -t 0

Timeout, zero seconds.

  1. this is a race-condition, depending on when the left-hand-side is ready to provide data. You can specify -t 5 but on a thrashing system even that is problematic.
  2. read -t is not standardised in SUSv3. It is in BSD sh, bash, zsh. It's not in ksh or dash.

So you can't just use #!/bin/sh and expect to have this.

The basic problem is that even if there's nothing on stdin now, that doesn't mean there won't be soon. Invoking a program normally leaves stdin connected to the terminal/whatever, so there's no way to tell what's needed.

So, to answer your question literally, you can do it, but in practice your options are:

  1. test if stdin is a tty: [ -t 0 ]
  2. use argv to control behaviour
深爱不及久伴 2024-08-31 23:52:03

您可以轻松实现与“cat”命令类似的行为,即从提供的文件列表中读取,或者如果未提供它们,则从标准输入中读取。

尽管您可能不会使用这个想法,但我认为这篇 Linux Journal 文章对您来说会很有趣 http://www.linuxjournal.com/content/define-if-shell-input-coming-terminal-or-pipe

:-)

You can easily implement a similar behaviour as the "cat" command, that is read from a list of provided files or if they're not provided, then read from the stdin.

Although you may not use this idea, I think this Linux Journal article will be interesting for you http://www.linuxjournal.com/content/determine-if-shell-input-coming-terminal-or-pipe

:-)

梦里人 2024-08-31 23:52:03

如果您不想以交互方式运行脚本,请使其将输入文件作为参数,而不是使用 stdin。有些程序使用标志或特殊文件名来指示它们应该从标准输入而不是文件中获取输入;在这种情况下,您可以在必要时处理命令行操作。

如果您希望脚本采用标准输入,为什么不让它具有交互性(或者至少表现得像其他 POSIX 工具一样)?

If you never want to run the script interactively, make it take the input file as a parameter, rather than using stdin. Some programs use a flag or a special filename to indicate that they should take input from standard input rather than from a file; that case lets you handle command line jockeying if necessary.

If you want your script to take the standard input, why don't you want to let it be interactive (or at least behave like other POSIX tools)?

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