让 tmux 将缓冲区复制到剪贴板

Dig*_*ers 124 keyboard-shortcuts tmux clipboard xclip

我试图找出一种体面的方法来将 tmux 缓冲区中的内容复制到剪贴板中。我尝试了一些不同的东西,比如

bind-key p select-pane -t 2 \; split-window 'xsel -i -b' \; paste-buffer
Run Code Online (Sandbox Code Playgroud)

这让我相当接近,我所要做的就是在我做前缀 p 之后点击 control-d。

我尝试通过这样做来解决这个问题

bind-key p select-pane -t 2 \; split-window 'xsel -i -b << HERE\; tmux paste-buffer\; echo HERE'
Run Code Online (Sandbox Code Playgroud)

但这根本行不通。事实上,如果我把它配对到只是

bind-key p select-pane -t 2 \; split-window 'xsel -i -b << HERE'
Run Code Online (Sandbox Code Playgroud)

它没有做任何事情,所以我假设拆分窗口不喜欢 shell 命令中的 << 。

有任何想法吗?

编辑:select-pane -t 2如果你愿意,你可以跳过,这并不重要。我只使用特定的布局,而窗格 2 是我在做其他事情时更喜欢拆分的布局,以便默认情况下进入涉及拆分的绑定。

小智 96

这应该有效:

# move x clipboard into tmux paste buffer
bind C-p run "tmux set-buffer \"$(xclip -o)\"; tmux paste-buffer"
# move tmux copy buffer into x clipboard
bind C-y run "tmux save-buffer - | xclip -i"
Run Code Online (Sandbox Code Playgroud)

  • `Cp` 的更好说明是:`bind Cp run "xclip -o | tmux load-buffer - ; tmux paste-buffer"` -- 没有引用问题或命令行限制问题。 (22认同)
  • 在“复制模式”下,tmux 是否有一个钩子可以将选择复制到剪贴板? (9认同)
  • 每次我以这种方式进行复制时,tmux 都会停止响应任何键盘快捷键。有什么解决办法吗? (6认同)
  • `xclip -o` 选项对我不起作用,所以我改为 `bind Cc run "tmux save-buffer - | xclip -selection c"\; 显示消息“缓冲区已复制到剪贴板”` (2认同)

Tyl*_*ien 42

copy-pipe命令是从 1.8 版开始添加的。它将选择复制到 tmux 缓冲区并将其通过管道传递给命令。现在不需要前缀绑定。下面是一个例子:

bind -t vi-copy y copy-pipe "xclip"

# For OS X users:
bind -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
Run Code Online (Sandbox Code Playgroud)

现在,当您在 中选择了一些文本时copy-modey会将该文本复制到 tmux 缓冲区以及操作系统剪贴板。但是,如果您想将文本从剪贴板获取到 tmux 缓冲区,这无济于事。

  • 这不再适用于 2017 年 4 月 20 日发布的 Tmux 2.4。相反,您需要使用`bind-key -T copy-mode-vi y send-keys -X copy-pipe "xclip"` 和 OS X: `bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy"` (6认同)
  • 在 Linux 下对我不起作用,但这个可以:http://unix.stackexchange.com/a/131074/13601 (2认同)

doc*_*hat 41

一个更简单的 Mac OS-X 解决方案

这建立在亚历克斯的回答基础上,并使用了当时不存在的东西。

如果您正在使用自制软件(如果您没有,为什么不使用?)那么您可以这样做:

brew install reattach-to-user-namespace
Run Code Online (Sandbox Code Playgroud)

然后在您的~/.tmux.conf

set-option -g default-command "reattach-to-user-namespace -l zsh" # or bash...
bind C-c run "tmux save-buffer - | reattach-to-user-namespace pbcopy"
bind C-v run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

要将缓冲区从 tmux(您应该已经使用 tmux 复制了一些内容)复制到 Mac 粘贴板,请使用<tmux-key> Control-c. 它现在可用于Command-vpbpaste

要从 Mac 粘贴板粘贴某些内容,请使用<tmux-key> Control-v.

  • 这个答案太棒了。我正在使用 `tmux show-buffer` 这导致换行问题 `tmux save-buffer -` 解决了它。 (2认同)

Gil*_*il' 25

这里的文件需要换行。例如,在shell脚本中,您可以编写

cat <<EOF >somefile; echo  done
file contents
EOF
Run Code Online (Sandbox Code Playgroud)

我不认为 tmux 可以让您在那里放置换行符,即使这样做了,这也不是一个好方法。如果数据本身HERE单独包含在一行中(例如,因为您正在复制您的.tmux.conf)怎么办?

我建议将缓冲区内容写入临时文件。未经测试:

bind-key p save-buffer ~/.tmux-buffer \; run-shell "xsel -i -b <~/.tmux-buffer && rm ~/.tmux-buffer"
Run Code Online (Sandbox Code Playgroud)

如果您在两个单独的 tmux 实例中使用此命令,则会出现竞争条件。我不知道如何解决这个问题。


小智 17

您可能想尝试tmux-yank 插件。它可以直接复制到系统剪贴板(OS X 和 Linux)和其他一些好东西,比如拉取当前的 shell 行。

  • 这是一个很棒的、干净的解决方案,应该被更多地考虑,因为它是一个比其他答案更近的答案。感谢分享! (8认同)

Jas*_*son 14

这是对全面答案的尝试。

先来一段历史

当第一次问这个问题时(2011 年 6 月),将文本从 Tmux 复制到剪贴板必须是一个两步过程,首先将所选文本复制到 Tmux 的缓冲区,然后将文本从 Tmux 的缓冲区复制到系统剪贴板。

在 1.8(2013 年 3 月)copy-pipe中添加了该命令,该命令允许您将所选文本直接复制到系统剪贴板(或其他目的地)中。

然后在 2.4(2017 年 4 月)中,关键表发生了重大变化,导致此页面上的许多答案已过时。

回答原来的问题

Linux

bind-key C-y run-shell "tmux save-buffer - | xclip -i -r > /dev/null" \; display-message "Copied tmux buffer to selection"
bind-key C-Y run-shell "tmux save-buffer - | xclip -i -r -selection clipboard > /dev/null" \; display-message "Copied tmux buffer to clipboard"
bind-key C-p run-shell "xclip -o | tmux load-buffer - ; tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

马克

如果您使用的是自制软件,那么您应该reattach-to-user-namespace通过在终端中运行以下命令来安装:

brew install reattach-to-user-namespace
Run Code Online (Sandbox Code Playgroud)

然后在你的 ~/.tmux.conf 中:

bind-key C-y run-shell "tmux save-buffer - | reattach-to-user-namespace pbcopy" \; display-message "Copied tmux buffer to clipboard"
bind-key C-p run-shell "reattach-to-user-namespace pbpaste | tmux load-buffer - ; tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

较短的方法(tmux>2.4 直接从剪贴板复制和粘贴选择)

注意:Linux 有两个版本,因为 Linux 有主剪贴板和辅助剪贴板(也称为选择)。

Linux

bind-key -T copy-mode-vi y send-keys -X copy-pipe "xclip -r" \; display-message "Copied to selection"
bind-key -T copy-mode-vi Y send-keys -X copy-pipe "xclip -r -selection clipboard" \; display-message "Copied to clipboard"
bind-key C-p run-shell "xclip -o | tmux load-buffer - && tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

马克

bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" \; display-message "Copied to clipboard"
Run Code Online (Sandbox Code Playgroud)

自定义这些命令

  • 如果您不希望该命令告诉您它在状态行中做了什么,那么只需删除display-message(以及\;它之前的 )。

  • 如果您使用的是Emacs的风格复制模式,而不是六然后替换的任何实例copy-mode-vicopy-mode

  • 如果您运行的是Linux,并要使用xsel,而不是xclip替代xclip -rxsel -i -pxclip -oxsel -o -p

  • -rxclip -r是可选的,它消除了最后的换行符。这对于复制命令很有用,然后当您粘贴它们时,它们不会立即执行。

  • 如果您通过 SSH 建立隧道,那么您应该咨询https://unix.stackexchange.com/a/354581/14252

参考:


小智 9

尝试不同的解决方案后,这是我的最终设置:

# move x clipboard into tmux paste buffer
bind C-p run "xclip -o | tmux load-buffer -
# move tmux copy buffer into x clipboard
bind C-y run "tmux save-buffer - | xclip -i -selection clipboard"
Run Code Online (Sandbox Code Playgroud)

使用 save-buffer 而不是 show-buffer 可以提供没有数据的真实数据,如分割时显示的换行符。

我还使用它在 tmux 复制模式下开始选择/复制:

bind-key -t vi-copy 'v' begin-selection
bind-key -t vi-copy 'y' copy-selection
Run Code Online (Sandbox Code Playgroud)

我想可以将复制选择与“y”键合并并将其移动到 x 剪贴板。


小智 7

我不喜欢有额外的按键,所以我想要一些更有野心的东西。使用 [ 进入复制模式,突出显示右侧文本,然后按 ] 将文本复制到剪贴板。

此外,tmux 喜欢在换行的表达式中包含换行符(奇怪的是,这些换行符在错误的位置!它们不是表达式在屏幕上换行的位置)。所以我希望 C-] 复制删除换行符的表达式。

在 tmux 1.6 上我试过这个:

bind [ copy-mode
bind -t vi-copy ] run "tmux send-keys Enter; tmux show-buffer | xclip -i -selection clipboard;"
bind -t vi-copy C-] run "tmux send-keys Enter; tmux show-buffer | perl -pe 's/\n//' | xclip -i -selection clipboard;"
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为 tmux 似乎不乐意将复杂的东西绑定到 vi-copy 表。所以我最终这样做了:

bind [ copy-mode \;                                                        \
    bind -n ] run                                                          \
    "tmux send-keys Enter;                                                 \
     tmux show-buffer | xclip -i -selection clipboard;                     \
     tmux unbind -n C-];                                                   \
     tmux unbind -n ]" \;                                                  \
    bind -n C-] run                                                        \
    "tmux send-keys Enter;                                                 \
     tmux show-buffer | perl -pe 's/\n//' | xclip -i -selection clipboard; \
     tmux unbind -n C-];                                                   \
     tmux unbind -n ]"
Run Code Online (Sandbox Code Playgroud)

这会导致奇怪的事情(] 或 C-] 会在您下次使用它们时表现得很有趣,但只有一次)如果您以除 ] 或 C-] 之外的其他方式退出复制模式。这可以通过我想象的更多绑定来修复,但这在大多数情况下都是我想要的。


小智 5

适用于 Mac OS X 的解决方案。请执行以下 2 个步骤:

  1. 使用 Chris Johnsen 的解决方法: https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard

  2. 将此代码添加到您的 tmux 配置 (~/.tmux.conf)

# paste clipboard into tmux buffer
bind v run-shell "reattach-to-user-namespace -l zsh -c 'tmux set-buffer \\"$(pbpaste)\\"; tmux paste-buffer'"
# put tmux buffer into x clipboard
bind y run-shell "reattach-to-user-namespace -l zsh -c 'tmux show-buffer | pbcopy'"
Run Code Online (Sandbox Code Playgroud)


Tux*_*ude 5

我编造的已接受答案的稍作修改的变体。

除了 xclip 的primary默认剪贴板(通过鼠标选择和鼠标中键单击获得的剪贴板)之外,我还更喜欢使用系统剪贴板(Ctrl-C、Ctrl-V)。要选择系统剪贴板,您需要将-selection clipboard参数传递给xclip.

另外,在将缓冲区复制到剪贴板时,我喜欢能够选择要复制的缓冲区。它是通过 using 完成的choose-buffer,然后将 buffer 参数传递给save-bufferusing -b %%

# Copy into clipboard
bind C-c choose-buffer "run \"tmux save-buffer -b %% - | xclip -i -selection clipboard\""
# Paste from clipboard
bind C-v run "xclip -o -selection clipboard | tmux load-buffer - ; tmux paste-buffer"
# Copy into primary
bind C-y choose-buffer "run \"tmux save-buffer -b %% - | xclip -i \""
# Paste from primary
bind C-p run "xclip -o | tmux load-buffer - ; tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

更新:不知何故,在 tmux 1.8 和我的两个 openSUSE 12.2 安装中,我发现通过管道从标准输入读取tmux run-shell调用 时挂起。xclip相反,我决定尝试一下xsel,这似乎有效。这些是使用 的等效键绑定xsel。我还习惯&&将命令链接到粘贴中以提高鲁棒性。

# Copy into clipboard
bind C-c choose-buffer "run \"tmux save-buffer -b '%%' - | xsel -i -b\""
# Paste from clipboard
bind C-v run "xsel -o -b | tmux load-buffer - && tmux paste-buffer"
# Copy into primary
bind C-y choose-buffer "run \"tmux save-buffer -b '%%' - | xsel -i\""
# Paste from primary
bind C-p run "xsel -o | tmux load-buffer - && tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)


Pla*_*ong 5

这是我相当冗长的答案,应该解决使用 xclip 从远程(ssh)tmux 会话复制缓冲区的两个主要问题:

1. xclip无响应

对我来说@Grauwolf 的回答不起作用xclip(使 tmux 窗格完全无响应)。我在Arch wiki 的 Tmux 页面中找到了原因:

xclip 也可以用于此目的,与 xsel 不同,它在打印不适合当前区域设置的原始比特流时效果更好。尽管如此,使用 xsel 而不是 xclip 更简洁,因为 xclip 在从 tmux 的缓冲区读取数据后不会关闭 STDOUT。因此,tmux 并不知道复制任务已完成,而是继续等待 xclip 的终止,从而导致 tmux 无响应。解决方法是将xclip 的 STDOUT 重定向到 /dev/null

所以绑定应该是:

bind-key C-y run "tmux save-buffer - | xclip -i -sel clip > /dev/null"
Run Code Online (Sandbox Code Playgroud)

现在,如果您的 tmux 会话是本地的,这将起作用。

2. xclip无法连接X

如果您使用 tmux 而不是 ssh -X,那么这很可能无法直接工作。

$DISPLAY这是因为需要正确设置shell 变量。

完整的解决方案

所以对我来说,完整的工作解决方案是将以下几行放入我的~/.tmux.conf

set-option -g update-environment "DISPLAY"
bind-key C-y run "export DISPLAY=`tmux show-env | sed -n 's/^DISPLAY=//p'`; tmux save-buffer - | xclip -i -selection clipboard >/dev/null"
# Or more concise:
bind-key C-y run "tmux save-buffer - | xclip -i -selection clipboard -d `tmux show-env | sed -n 's/^DISPLAY=//p'` >/dev/null
Run Code Online (Sandbox Code Playgroud)

对于从主要粘贴:

bind-key C-p run "xclip -d `tmux show-env | sed -n s/^DISPLAY=//p` -o | tmux load-buffer - && tmux paste-buffer"
Run Code Online (Sandbox Code Playgroud)

我不完全理解为什么$DISPLAY在 source 时没有正确设置 .tmux.conf,所以这就是为什么我必须用tmux show-envand提取它sed

如果您的 tmux >= 1.8,您可以使用以下命令调整此命令copy-pipe

bind-key -t vi-copy y copy-pipe 'xclip -in -selection clipboard -d `tmux show-env | sed -n s/^DISPLAY=//p` >/dev/null'
Run Code Online (Sandbox Code Playgroud)