To which stream does xsel print the no newline warning?

Note that that's the behaviour of xsel in not yet released versions of xsel. Introduced by this change in 2008.

It's common for X selections to contain text that doesn't end in newline characters. If you dump it as is, that results in an unterminated line being displayed. With old shells like bash the display becomes:

bash-4.4$ xsel -b
xselbash-4.4$

(here with the CLIPBOARD selection containing xsel). The next prompt ends up being appended to the content of the selection.

Modern shells like zsh or fish work around that be detecting when the output of the last command doesn't end in newline and give you a visual indication then.

With zsh:

prompt% xsel -p
xsel%
prompt%

(the reverse-video % after xsel being the indication that a newline was missing).

With fish:

prompt ~> xsel -p
x⏎
prompt ~>

Those newer xsel give you that visual indication themselves:

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

Now, that is only useful if xsel is run at the prompt of an old interactive shell.

In particular, that "No newline" indication would not be desirable when used as:

selection=$(xsel -b)

(where xsel's stdout is a pipe) or:

xsel -b > selection.txt

(where xsel's stdout is a regular file).

That's why xsel only outputs that indication only when stdout goes to a tty device.

Now, where does it display it? Well, the intention is to display it on that tty device. If you run it under strace, you'll see:

$ 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 +++

Which confirms the source: it's output on stderr. And when stdout is not a terminal:

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

It's not output at all. Now one might argue it's a bit silly to output on stderr when the intent is to output that notification to the terminal (stderr could be redirected to a log file for instance as in xsel -b 2> logfile), but:

  • Generally, when stdout is a terminal device, stderr is as well.
  • That means you can disable that notification when run in a terminal with xsel -b 2> /dev/null which would be more efficient than xsel -b | cat.
  • The isatty() would return true for a serial device that is not connected to a terminal.