6

xsel is a program with which you can access system clipboard from command line. If there is no newline at the end of copied content, it prints a warning after the clipboard content like this:

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

Earlier I used to think that this warning is printed to the standard error, but today I found that the warning is not there even if the standard error is merged with the standard output.xsel-b |& less just prints the copied text, without the warning. Why does it behave like this?

4

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.
1

It's simple enough to test with:

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

The message will be in one of the two files. If it's in xsel.out, then the message is through standard output; if it is in the other file, then it is through standard error; if it is in neigher, then something very strange is happening, and you need to have a long, serious talk with your kernel.

  • 1
    It's perfectly possible for a process to write to the tty without regard for stdout or stderr: ( echo "on tty" >$(tty); echo "on stdout" >&1; echo "on stderr" >&2 ) 1>out 2>err – Kusalananda Jan 13 '17 at 16:57
  • 1
    As it happens, xsel no longer outputs that text when stdout does not go to a terminal device. xsel -b 2> xsel.err while stdout is a terminal would store that text in xsel.err though. – Stéphane Chazelas Jan 13 '17 at 16:57
  • @DopeGhoti the clipboard content goes to xsel.out and xsel.err is empty. – saga Jan 14 '17 at 5:08
  • @DopeGhoti can you help me out, the kernel is intimidating me. How should I start the conversation? – saga Jan 14 '17 at 5:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.