假设我的代码开头有以下内容:
exec < file
如果我理解正确的话,这意味着所有尝试从 stdin 读取的命令实际上都会从 读取file
。
但是如果我有cmd1 | cmd2
,cmd2
将从cmd1
的输出中读取还是file
?
答案1
如果我理解正确的话,这意味着所有试图从 stdin 读取的命令实际上都会从文件中读取
如果满足以下条件,则从其标准输入读取的命令将从常规文件读取:它是stdin 恰好是一个常规文件。从其 stdin 读取的命令将从终端或 fifo(也是文件) 如果它是stdin 恰好分别是一个终端或 fifo。
一个命令的标准输入可以与另一个命令的标准输入不同。
在由 解释的脚本中bash
,仅exec < file
重定向此特定进程的标准输入bash
。如果后续命令继承了标准输入,则它们将受到影响,但无论您是否使用,继承都以相同的方式发生exec < file
。
如果你运行它cmd0
,它将从解释器继承 stdin 和 stdout (和 stderr) bash
。解释器的 stdin 和 stdoutbash
是什么并不重要;机制始终相同。
如果你运行,cmd1 | cmd2 | … | cmdN
那么cmd1
将从解释中继承 stdin bash
,并cmdN
从解释中继承 stdout bash
。其他 stdin 和 stdouts 将形成一个管道(的 stdoutcmd1
连接到的 stdincmd2
等等)。解释的 stdin 和 stdout 是什么并不重要bash
;机制始终相同。
您使用的事实exec < file
与机制本身无关。某些命令将从解释器继承 stdin 和/或 stdout bash
。如果没有,exec < file
它们将继承某物他们exec < file
将继承其他东西作为标准输入。
这意味着exec < file
可以影响某些命令,但仅限于从解释器继承 stdin 的命令bash
。您的cmd1
确实继承了解释器的 stdin bash
,但cmd2
没有。
假设您cmd2
只是从其 stdin 读取,它将从 的输出中读取cmd1
。 前者exec < file
并不重要。 (请注意,通常cmd2
可能会重定向、忽略或关闭其 stdin;设计用于管道的命令不会这样做,除非被告知。)
您可以在脚本中测试这一点:
#!/bin/bash
# Don't run this in an interactive shell. Run as a script.
exec < /etc/fstab
echo foo | cat
wc -l
请注意,如果您将上述代码粘贴到交互式环境中,bash
那么您将更改其自身的 stdin bash
,并且它最终将在 EOF 时退出。为方便起见,下面是一个可以在交互式 shell 中运行而不终止它的版本:
bash -c '
exec < /etc/fstab
echo foo | cat
wc -l
'
输出应为foo
(证明cat
读取的输出),后跟一个数字,表示(证明读取自)echo
中的行数。fstab
wc
fstab