xsel 将 no newline 警告打印到哪个流?

xsel 将 no newline 警告打印到哪个流?

xsel 是一个可以从命令行访问系统剪贴板的程序。如果复制内容末尾没有换行符,它会在剪贴板内容后打印一条警告,如下所示:

$ xsel -b
copied text
\ No newline at end of selection

早些时候我曾经认为这个警告会打印到标准错误中,但今天我发现即使标准错误与标准输出合并,警告也不存在。xsel-b |& less仅打印复制的文本,没有警告。为什么它会这样?

答案1

请注意,这是xsel尚未发布的xsel.介绍者这个变化在2008。

X 选择包含不以换行符结尾的文本是很常见的。如果按原样转储它,则会导致显示未终止的行。使用像bash显示器这样的旧外壳会变成:

bash-4.4$ xsel -b
xselbash-4.4$

(此处的剪贴板选择包含xsel)。下一个提示最终会附加到所选内容中。

现代 shell 喜欢zshfish解决这个问题,即检测最后一个命令的输出何时不以换行符结尾,然后给您一个视觉指示。

zsh

prompt% xsel -p
xsel%
prompt%

(指示缺少换行符%后的反向视频)。xsel

fish

prompt ~> xsel -p
x⏎
prompt ~>

那些较新的xsel给你视觉指示本身:

bash-4.4$ xsel -b
xsel
\ No newline at end of selection
bash-4.4$

现在,只有当 xsel 在旧交互式 shell 的提示符下运行时,这才有用。

特别是,当用作以下情况时,“无换行符”指示是不可取的:

selection=$(xsel -b)

(其中xselstdout 是管道)或:

xsel -b > selection.txt

(其中xselstdout 是常规文件)。

这就是为什么xsel只有当 stdout 转到 tty 设备时才输出该指示。

现在,它在哪里显示它?嗯,目的是在 tty 设备上显示它。如果你在 strace 下运行它,你会看到:

$ strace -e write ./xsel -b
write(1, "xsel", 4xsel)                     = 4
write(2, "\n\\ No newline at end of selectio"..., 34
\ No newline at end of selection
) = 34
+++ exited with 0 +++

这证实了来源:它在 stderr 上输出。当 stdout 不是终端时:

$ strace -e write ./xsel -b  > /dev/null
write(1, "$ strace -e write ./xsel -b | ca"..., 104) = 104
+++ exited with 0 +++

根本就不是输出。现在,有人可能会说,当意图将该通知输出到终端时,在 stderr 上输出有点愚蠢(stderr 可以重定向到日志文件,例如xsel -b 2> logfile),但是:

  • 通常,当 stdout 是终端设备时,stderr 也是终端设备。
  • 这意味着您可以在终端中运行时禁用该通知,xsel -b 2> /dev/null这比xsel -b | cat.
  • isatty()对于未连接到终端的串行设备,将返回 true 。

答案2

测试起来很简单:

xsel -b > xsel.out 2> xsel.err

该消息将位于两个文件之一中。如果在 中xsel.out,则消息是通过标准输出;如果它在另一个文件中,那么它是通过标准错误;如果它在 neigher 中,那么正在发生一些非常奇怪的事情,您需要与内核进行一次长时间、严肃的交谈。

相关内容