There are two command-line tools (in two different packages) to access the X clipboard:
xclip
xsel
I would love to know the difference between those two and hear a recommendation which one to use in which cases.
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It only takes a minute to sign up.
Sign up to join this communityBoth xclip
and xsel
can store text into 3 different selections (by default it is primary selection). From experience I know that primary selection is basically what you high-light and released with the middle mouse click (which corresponds to pressing both right and left touchpad key on a laptop). The clipboard is the traditional CtrlV.
By examining the man
pages for both, however, I've discovered that xclip
wins in one aspect - reading from an input file:
$ cat testfile.txt
HELLOWORLD
$ xclip -selection clipboard testfile.txt
$ HELLOWORLD
mksh: HELLOWORLD: not found
$ xsel testfile.txt
Usage: xsel [options]
Manipulate the X sele . . . (usage page goes on)
Of course you could use shell redirection with xsel
to get around that
$ xsel --clipboard < testfile.txt
$ HELLOWORLD
mksh: HELLOWORLD: not found
xclip
also wins in the fact that you can output the contents of clipboard to file (which is perhaps useful when you want to redirect PRIMARY selection , i.e. highlights). xsel
offers only output to stdout
xsel
can only operate through STDIN/STDOUT, while xclip
also can use real files there? How boring! Well, I made friends with xsel
a while ago and can live with using shell redirections to files, so I'll keep using that.
xclip
today and wondered if it was the right choice. Your answer confirmed it was because I'm creating file from clipboard to use with diff
command. +1 Thanks :)
Mar 18, 2017 at 17:20
xclip
not closing STDOUT. If you use xclip in a script or function that hangs, this is likely the cause.
Sep 18, 2019 at 6:58
In addition to @Serg answer, there is a piece of information from the Tmux page in the Arch Wiki that can be useful in some specific cases:
Unlike xsel [xclip] works better when printing a raw bitstream that does not fit the current locale. Nevertheless, it is neater to use xsel because xclip does not close
STDOUT
after it has read from the tmux buffer. As such, tmux does not know that the copy task has completed, and continues to wait for xclip to terminate, thereby rendering tmux unresponsive. A workaround is to redirectSTDOUT
to/dev/null
:
xclip
is a major problem if you encounter it. I wasted 2 hours debugging it. I finally switched to xsel -bi
and xsel -bo
.
Sep 18, 2019 at 6:56
xclip
over a forwarded X session. Explicitly closing stdout
and stderr
got things to work as I needed (e.g. somecmd | ssh -X remote 'xclip -i -sel clip -d :0 >&- 2>&-'
)
Something else to keep in mind, xsel
has fewer dependencies than xclip
:
# apt-cache depends xsel
xsel
Depends: libc6
Depends: libx11-6
Conflicts: xsel:i386
# apt-cache depends xclip
xclip
Depends: libc6
Depends: libx11-6
Depends: libxmu6
Conflicts: xclip:i386
Use xclip
, because xsel
can not extract binary data from clipboard, such as screenshots. For example, save screenshot to clipboard:
$ maim -s | xclip -selection clipboard -t image/png
Then save to file and compare output:
$ xclip -o -selection clipboard > 1xclip
$ xsel -o --clipboard > 1xsel
$ ls -go 1*
-rw-rw-r-- 1 11948 Sep 26 20:13 1xclip
-rw-rw-r-- 1 0 Sep 26 20:13 1xsel
xclip
isn't necessarily always able to handle binary data either, e.g. when using the "Copy to clipboard" button from gnome-screenshot I get no output at all. When copying an image with Ctrl+C from e.g. a LibreOffice Document, it only works if I manually specify the target type like xclip -o -t image/png -selection clipboard
.
gnome-screenshot
at all, but that's another issue - gitlab.gnome.org/GNOME/gnome-screenshot/issues/14
Sep 28, 2018 at 9:32
There is one other reason to use xclip over xsel – xclip can manipulate cut buffer 0, by passing -selection buffer-cut
, which xsel cannot do.
It's relatively easy to allow it to manipulate the other cut buffers as well; here is my patch, though it's not well-tested and comes with no guarantees.
diff --git a/xclip.c b/xclip.c
index 5fc760cb7..eeb05f662 100644
--- a/xclip.c
+++ b/xclip.c
@@ -35,11 +35,12 @@
#include "xclib.h"
/* command line option table for XrmParseCommand() */
-XrmOptionDescRec opt_tab[14];
+XrmOptionDescRec opt_tab[15];
/* Options that get set on the command line */
int sloop = 0; /* number of loops */
char *sdisp = NULL; /* X display to connect to */
+int bufnum = 0; /* Cut buffer number to use */
Atom sseln = XA_PRIMARY; /* X selection to work with */
Atom target = XA_STRING;
@@ -165,6 +166,9 @@ doOptSel(void)
break;
case 'b':
sseln = XA_STRING;
+ if (XrmGetResource(opt_db, "xclip.buffer", "Xclip.Buffer", &rec_typ, &rec_val)) {
+ bufnum = atoi(&rec_val.addr[0]);
+ }
break;
}
@@ -177,8 +181,10 @@ doOptSel(void)
fprintf(stderr, "XA_SECONDARY");
if (sseln == XA_CLIPBOARD(dpy))
fprintf(stderr, "XA_CLIPBOARD");
- if (sseln == XA_STRING)
+ if (sseln == XA_STRING) {
fprintf(stderr, "XA_STRING");
+ fprintf(stderr, "\nUsing buffer number %d", bufnum);
+ }
fprintf(stderr, "\n");
}
@@ -276,7 +282,7 @@ doIn(Window win, const char *progname)
/* Handle cut buffer if needed */
if (sseln == XA_STRING) {
- XStoreBuffer(dpy, (char *) sel_buf, (int) sel_len, 0);
+ XStoreBuffer(dpy, (char *) sel_buf, (int) sel_len, bufnum);
return EXIT_SUCCESS;
}
@@ -445,7 +451,7 @@ doOut(Window win)
unsigned int context = XCLIB_XCOUT_NONE;
if (sseln == XA_STRING)
- sel_buf = (unsigned char *) XFetchBuffer(dpy, (int *) &sel_len, 0);
+ sel_buf = (unsigned char *) XFetchBuffer(dpy, (int *) &sel_len, bufnum);
else {
while (1) {
/* only get an event if xcout() is doing something */
@@ -595,6 +601,11 @@ main(int argc, char *argv[])
opt_tab[13].argKind = XrmoptionNoArg;
opt_tab[13].value = (XPointer) xcstrdup(ST);
+ opt_tab[14].option = xcstrdup("-buffer");
+ opt_tab[14].specifier = xcstrdup(".buffer");
+ opt_tab[14].argKind = XrmoptionSepArg;
+ opt_tab[14].value = (XPointer) NULL;
+
/* parse command line options */
doOptMain(argc, argv);
For me xclip
will let zsh shell exit
very slowly when using guake
.
Like run command: $ pwd | xclip -selection c
.
Then run $ exit
to quit shell.
$ exit
need seconds to quit.
xsel
is good with this situation.
xclip
has this special feature to remove last empty line of copied selection where xsel
don't have this option.
man xclip
-rmlastnl remove the last newline charater if present