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 喜欢zsh
或fish
解决这个问题,即检测最后一个命令的输出何时不以换行符结尾,然后给您一个视觉指示。
和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)
(其中xsel
stdout 是管道)或:
xsel -b > selection.txt
(其中xsel
stdout 是常规文件)。
这就是为什么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 中,那么正在发生一些非常奇怪的事情,您需要与内核进行一次长时间、严肃的交谈。