Bash:清空标准输入(stdin)

4

我有一个bash脚本,主要在交互模式下使用。但是有时候我会将一些输入通过管道传递给脚本。在使用循环处理标准输入后,我使用“-i”(交互式)复制文件。然而,在管道模式下,这个操作永远不会被执行(我猜想)因为标准输入没有被刷新。以下是一个简单的示例:

#!/bin/bash
while read line
do
    echo $line
done
# the next line does not execute 
cp -i afile bfile

将以下内容放入t.sh文件中,并执行以下命令: ls | ./t.sh

read命令未被执行。 在读取之前需要清空stdin。如何做到这一点呢?

2个回答

6

这与清空无关。你的标准输入是ls的输出,你已经通过while循环读取了所有内容,所以read会立即获得EOF。如果你想从终端读取一些东西,可以尝试以下方法:

#!/bin/bash
while read line
do
    echo $line
done
# the next line does execute 
read -p "y/n" x < /dev/tty
echo "got $x"

我尝试了< /dev/tty和< $(tty)。但是都不起作用,第二个会出现错误。./rtest2.sh: line 122: $(tty): ambiguous redirect实际上,如果你看到这个问题,我的问题在于“cp -i”命令。我给出的代码示例只是为了演示,因为代码本身很大。可以使用cp -i替换read命令来解决问题。 - rahul
@rahul 对我来说使用 cp -i 同样有效。如果对你不起作用,请发布你的系统详细信息(uname -a),并更详细地说明它为什么不起作用。 - unbeli
我又试了一遍。哇,"< dev/tty" 终于起作用了!非常感谢。 - rahul
这在 zsh 中可行吗? - alper

0

我不确定在这里实现你想要的是可能的(即让read从用户那里获取输入而不是从ls获取)。问题在于,脚本的所有标准输入都来自管道,没有例外。这是相同的文件描述符,因此它不会因为你想要它而“切换”到终端。

一个选项是像这样运行ls作为脚本的子进程:

#!/bin/bash

ls | while read line
do
    echo $line
done

read -p "y/n" x
echo "got $x"

遗憾的是,我经常直接从命令行使用这个程序,而不通过管道输入。在这种情况下,它会交互式地工作,就像一个 shell,提示我输入命令。<p> 有时,我通过一些过滤器将文件内容传输给它,或者我直接通过管道对一些内容进行 grep 和 sed 处理,并传输给它。 - rahul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接