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.


7 Answers 7


Both 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                                                             

$ xclip -selection clipboard testfile.txt

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                                              

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

  • 6
    So there's no difference except that 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.
    – Byte Commander
    Commented Dec 4, 2015 at 10:38
  • 2
    Unless I've missed something in the man pages or there are some hidden features, that's really all there is to these two programs :) Both are doing good enough job, so I guess it's more of a preference than anything Commented Dec 4, 2015 at 12:14
  • 1
    I installed 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 :) Commented Mar 18, 2017 at 17:20
  • 1
    I ran across a post has an excellent wrapper function for xclip that may tip the scale far in it's favor. madebynathan.com/2011/10/04/a-nicer-way-to-use-xclip
    – dragon788
    Commented Jun 16, 2017 at 17:49
  • 2
    Notice that there is another answer that explains an issue with xclip not closing STDOUT. If you use xclip in a script or function that hangs, this is likely the cause. Commented 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 redirect STDOUT to /dev/null:

  • 7
    This not closing STDOUT issue with xclip is a major problem if you encounter it. I wasted 2 hours debugging it. I finally switched to xsel -bi and xsel -bo. Commented Sep 18, 2019 at 6:56
  • Thank you! Finally know why I was having issues with 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>&-')
    – Saites
    Commented Feb 3, 2022 at 3:24

Something else to keep in mind, xsel has fewer dependencies than xclip:

# apt-cache depends xsel
  Depends: libc6
  Depends: libx11-6
  Conflicts: xsel:i386

# apt-cache depends xclip
  Depends: libc6
  Depends: libx11-6
  Depends: libxmu6
  Conflicts: xclip:i386
  • 2
    I suspect most installations already have libxmu6 though, many packages such as xterm, x11-apps, and x11-utils depend on it.
    – JoshB
    Commented Aug 5, 2016 at 7:32

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
  • 1
    I find that 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.
    – Byte Commander
    Commented Sep 26, 2018 at 20:28
  • 2
    I don't get output from gnome-screenshot at all, but that's another issue - gitlab.gnome.org/GNOME/gnome-screenshot/issues/14 Commented 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)
    case 'b':
        sseln = XA_STRING;
+       if (XrmGetResource(opt_db, "xclip.buffer", "Xclip.Buffer", &rec_typ, &rec_val)) {
+           bufnum = atoi(&rec_val.addr[0]);
+       }

@@ -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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .