我想实现一个zsh
行为不同的脚本,具体取决于它是否直接在 shell 的 CLI 上调用。
起初我以为脚本可以通过查找i
的值来做到这一点$-
,但我错了。
事实上,当我从命令行运行下面的脚本时
#!/bin/zsh
printf -- '%s\n' "$-"
...我得到的输出不包括i
1。
我的 shell 脚本还有其他方法可以找出这些信息吗?
注意:虽然我zsh
目前正在编写脚本,但我也想知道bash
脚本的答案是什么。如果答案取决于OS
,我主要对 Linux 和 Darwin 感兴趣。
1569X
如果有人想知道的话,脚本的输出是。
$-
包含i
当 shell 本身是交互式 shell 时,当它发出提示时,允许您在终端上输入和编辑命令行,执行作业控制等。脚本通常由非交互式 shell 解释。如果将脚本调用为
./the-script
orzsh ./the-script
,则该zsh
实例不是交互式的。交互式 shell 解释脚本的唯一情况是当您告诉交互式 shell 用source ./the-script
或之类的东西解释其中的代码时eval "$(<the-script)"
。在这里,在我看来,您似乎更想知道脚本是否是从终端中调用的,就像您想知道用户是否可以通过终端与之交互一样。
[
/命令(内置于test
zsh 和 bash 以及大多数其他类似 Bourne 的 shell,但在 POSIX 系统上也应该作为独立命令存在)可以通过其-t
操作员告诉您。该-t
运算符采用一个¹数字参数,即文件描述符。[ -t 0 ]
test -t 0
如果文件描述符 0 在终端设备上打开,则返回 true 。文件描述符 0 是标准输入,1 是标准输出,2 是标准错误,所有其他 fd 没有任何保留的特殊含义。因此,在您的脚本中,您可以执行以下操作:
如果您想检查脚本是否从终端会话中运行,即使它的输入和/或输出可能被重定向到终端设备以外的其他文件,您可以检查是否有终端连接到脚本的会话,例如:
如果你想知道它是什么终端设备:
(有关与 fd 3 的小舞背后的原因,请参阅此后续问答)。
¹ 在较早的
test
/[
实现中,该参数是可选的并且[ -t ]
是[ -t 1 ]
. POSIX 不再允许这样做,因为这[ "$var" ]
与[ -n "$var" ]
. 尽管如此,您仍然会发现它ksh93
仍然会检查 stdout 是否进入 tty,[ -t ]
尽管只有当-t
是文字时;var=-t; [ "$var" ]
即使标准输出不在终端上,也返回 true。