PuTTYを使ってリモートのシェル操作でWindowsのクリップボードにテキストをコピーする
まずは結論から。
PuTTYで「Ctrl-Insert」やマウスを使った方法ではなく、ShellやVimの操作でホストOSであるWindowsにコピーをする方法というのがこのエントリーのお話です。
前から欲しいなーと思っていた機能でなかなかやり方がわからなかったですが、あるパッチを発見したのでそれをちょっとだけカスタマイズして概ね満足できるレベルで利用することができるようになりました。
やりたいこと
- vimのVisualモードで指定した範囲をWindowsのクリップボードにコピーしたい
- Screenのコピーモードで指定したテキストをWindiwsのクリップボードにコピーしたい
- Shellで「cygwin の /dev/clipboard」みたいな事ができたらいいな
- 仮想環境とかディストリとかcolinuxとかCygwinとかその他環境で差異なく利用したい
- ログをコピーとかSCPでいちいちやりとりするのが面倒くさい
- サーバー・クライアントでデーモンを起動して共有するという方法は環境構築で厳しいのでちょっと辛い
特にvimの操作でvisualmodeの時はPuTTYの操作でWindowsのクリップボードに格納できないというのが常々きついなーと思っていました。
実現方法
PuTTYなどの仮想端末ソフトがリモートホストとは唯一の接点なのでPuTTYの操作でなんとかならないかな?と探したところ下記のパッチを発見。*1
PuTTYのリモートプリント機能を利用してテキストをホストOSのWindowsに送るというものです。
リモートホストでリモート印刷を開始するechoコマンド(標準出力で仮想端末PuTTYにシグナルを送信)を実行し、その後に送信される標準出力のテキストがバッファされ、リモート印刷を終了するとWindowsのクリップボードに格納されるという仕組みです。
パッチファイルとコンパイル済みのPuTTYはこちら。
ただ現在のパッチはマルチバイトに対応していないので文字化けします。
操作方法
シェルで利用する
Diomidis Spinellisさんのサイトからwinclipというシェルスクリプトをダウンロードします。
winclipの内容
#!/bin/sh echo -n '^[''[5i' cat $* echo -n '^[''[4i'
2行目がリモート印刷開始、3行目が標準入力を標準出力する、4行目がリモート印刷開始。
shellは実行権限をつけておきます。エスケープコード「\033」に気をつけてください。
文字列で「^[」としても駄目です。
参考情報
Terminal Emulator and Thin Client Software: Century Software
http://www.censoft.com/support/kb/?cat=34
利用するときは下記の2通りの方法があります。winclipはパスを通しておくと便利です。
例としてはwinclipシェルスクリプトはホームディレクトリにあるとします。
パイプを利用する
$ ls -la | ~/winclip
lsで標準出力されたテキストがWindowsのクリップボードに格納されます。
ファイル名を指定する
$ ~/winclip hogehoge.txt $ ~/winclip fugafuga.log $ ~/winclip hogescript.pl
screenのコピーモードで利用する
画面交換ファイルを活用します。
.screenrcに追記します。
bufferfile $HOME/.screen_exchange bind ^y eval 'exec sh -c "~/winclip ~/.screen_exchange"'
オペレーションは2手順です。
vimのビジュアルモードで利用する
画面交換ファイルっぽく一時ファイルを作成して活用します。
vimから:!やsystem関数を使ってvim内から直接標準出力を試みましたが、リモートプリンタがらみで応答がなかったり、コマンドラインで表示されるvimのメッセージが標準出力に含まれてしまったりしたので、最終的に一時ファイルを使う形で妥協しました。
.vimrcに追記します。
let g:vim_exchange_file = $HOME . '/.vim_exchange' let g:winclip = $HOME . '/winclip' vnoremap <silent><Space>Y :call WinclipLine()<CR> function! WinclipLine() range call writefile(getline(a:firstline, a:lastline), g:vim_exchange_file, 'b') "silent! execute ":'<,'>w! " g:vim_exchange_file silent! execute ':!' g:winclip ' ' g:vim_exchange_file call system("rm -f " . g:vim_exchange_file) endfunction " 未実装 "vnoremap <silent><Space>y y:call Winclip()<CR> "function! Winclip() " " TODO:レジスタ汚染&エスケープ処理。このまま使うと危険あり。 " let l:yank_text = @" " silent! execute ":!echo '" . l:yank_text ."' > " g:vim_exchange_file " silent! execute ':!' g:winclip ' ' g:vim_exchange_file " call system("rm -f " . g:vim_exchange_file) "endfunction
テキストを選択中に「
あと選択中のテキストのみ「
もし選択範囲を行指定ではなく選択中のテキストでコピーしたいのであればscreenで代用できます。
パッチをPuTTYの設定とダウンロード
ごった煮版(2007年8月6)にパッチをあてました。
パッチの当て方は過去のエントリーを参考にどうぞ。
以前にIMEのカーソル色切り替えとまとめてしまったので、今回の件と別の余分な機能がついてしまっています。
このパッチに関して蛭子屋さんに問い合わせしないようにお願いします。
パッチファイル
Gistに貼り付けました。
patchをあてる時はsjisかつ改行コードはLFにする必要があります。
通常利用のリモートプリンタは使用できないようにし、デフォルトで必ずwinclipの機能を使うように変更してあります。
コンパイル済みのPuTTY
コンパイル済みのzipファイルをこちらからダウンロードできるようにしておきました。