我有一个脚本要求用户在终端中输入,因此,如果使用重定向到文件的 stdout 调用脚本,则用户在提示符上没有上下文。所以我想将标准输出复制到两个站点。
该脚本输出一个微积分,因此允许 stdout 重定向仍然有意义。
但是如果提供了 stdin(类似于 yes 命令或非交互式上下文,如 cron),则完全允许输出在 tty 中不需要是有意义的。
所以我想做一些类似的逻辑:
If (test -t 0 && ! test -t 1);
// Tell stdout to print everything to tty as well
这可能吗?还是根本上就不合适?
答案1
请注意,如果您关心的是提示字符串,它通常应该转到 stderr。这就是大多数公用事业公司在发出提示时所做的事情。例如,请参阅read 'var?prompt
或 ksh/zsh/yashread -p prompt var
或bash
。
这样,它就与正常输出分开,然后您可以安全地重定向。
要仍然执行您所要求的操作,并在 stdin 位于 tty 上但 stdout 不在 tty 上时将输出发送到控制 tty,在包括 ksh93、zsh 或 bash 在内的一些 shell 中,您可以执行以下操作:
if [[ -t 0 && ! -t 1 ]]; then
exec > >(tee /dev/tty)
fi
但由于它tee
是在后台运行的,您可能会发现它到终端的输出在错误的时间出现。例如:
$ zsh -c 'exec > >(tee /dev/tty); print before; read "var?Prompt: "; print -r "after: $var"' > /dev/null
Prompt: before
what?
after: what?
已before
到达 tty后 read
发出了提示。
因此,要在全局范围内执行这些重定向,您需要对每个命令执行此操作,或者至少对发出提示或自行写入 stderr 或终端的命令之间的每组命令执行此操作,甚至是 stdout/stderr每个命令可能会以奇怪的顺序显示。
#! /bin/zsh -
if [[ -t 0 && ! -t 1 ]]; then
alias -g '{#}=>&1 > /dev/tty'
else
alias -g '{#}='
fi
print before {#}
read 'var?prompt: '
print -r after: $var {#}
tee
(当 fd 被重定向多次时,这里使用 zsh 的内置工具)。