为什么我没有在while循环中获取终端名称?

时间:2017-01-31 11:14:42

标签: bash

#! /bin/bash

while read line
do
 tty
done < file

i=1
while [ $i -lt 5 ]; do
 tty
let i=$i+1
done 
  

第一个循环给出输出:不是tty

     

第二个循环给出输出:/ dev / pts / 14

     

为什么我没有在第一个循环中获得终端名称?

2 个答案:

答案 0 :(得分:2)

如果您阅读the tty manual page,您会看到它:

  

打印连接到标准输入的终端的文件名。

强调我的

由于您将标准输入重定向为文件,因此tty命令将报告它未连接到tty。

答案 1 :(得分:1)

tty看到标准输入被定向,因为它位于一个循环中,其循环标准输入从文件中重定向。

你可以通过使用不同的文件描述符来实现你想要做的事情,而不是被认为是&#34;标准的&#34; (这是文件描述符0)。

while IFS= read -r -u 5 line
do
  tty
done 5< file

-u 5选项告诉read从文件描述符5中读取。5<重定向告诉Bash获取文件的内容并使其与文件描述符5一起使用。

当您需要避免在循环中捕获标准输入时,此技术非常有用,例如,如果您想要用户输入。

它也适用于进程替换,它允许重定向任意命令的输出:

while IFS= read -r -u 5 line
do
  tty
done 5< <(any_command with arguments)

在这种情况下,<()是一个表达式,它创建一个FIFO特殊文件,执行所述命令并将该命令的输出作为输入提供给FIFO。该表达式生成一个文件名(FIFO的实际路径),该文件与任何其他文件一样,用于重定向。

这通常比使用管道到while循环更好,因为循环内部在与脚本的其余部分相同的上下文中执行,避免了子shell:因此循环内部的变量赋值将在循环中可见退出。