Tmux Clipboard – How to Copy from/to Tmux Clipboard with Shell Pipes

pipeshellterminalterminal-multiplexertmux

When working in a shell environment I run fairly often into the need to copy 'intermediate pipe output' around (eg. from/to already running editors, to other shells, other machines, etc.).

When in a windowing environment, an easy (and generic) method to solve this is often via the system clipboard, eg.:

  • X11: ... | xsel -i / xsel -o | ...
  • OS X: ... | pbcopy / pbpaste | ...

How can I get similarly convenient behavior using the tmux copy/paste facility?

Best Answer

tl;dr

  • ... | tmux loadb -
  • tmux saveb - | ...

Explanation & Background

In tmux, all copy/paste activity goes through the buffer stack where the top (index 0) is the most recently copied text and will be used for pasting when no buffer index is explicitly provided with -b. You can inspect the current buffers with tmux list-buffers or the default shortcut tmux-prefix+#.

There are two ways for piping into a new tmux buffer at the top of the stack, set-buffer taking a string argument, and load-buffer taking a file argument. To pipe into a buffer you usually want to use load-buffer with stdin, eg.:

print -l **/* | tmux loadb -

Pasting this back into editors and such is pretty obvious (tmux-prefix+] or whatever you've bound paste-buffer to), however, accessing the paste from inside the shell isn't, because invoking paste-buffer will write the paste into stdout, which ends up in your terminal's edit buffer, and any newline in the paste will cause the shell to execute whatever has been pasted so far (potentially a great way to ruin your day).

There are a couple of ways to approach this:

  1. tmux pasteb -s ' ' : -s replaces all line endings (separators) with whatever separator you provide. However you still get the behavior of paste-buffer which means that the paste ends up in your terminal edit buffer, which may be what you want, but usually isn't.
  2. tmux showb | ... : show-buffer prints the buffer to stdout, and is almost what's required, but as Chris Johnsen mentions in the comments, show-buffer performs octal encoding of non-printable ASCII characters and non-ASCII characters. This unfortunately breaks often enough to be annoying, with even simple things like null terminated strings or accented latin characters (eg. (in zsh) print -N รก | tmux loadb - ; tmux showb prints \303\241\000 ).
  3. tmux saveb - | ... : save-buffer does simply the reverse of load-buffer and writes the raw bytes unmodified into stdout, which is what's desired in most cases. You could then continue to assemble another pipe, and eg. pass through | xargs -n1 -I{} ... to process line wise, etc..
Related Question