header

WSLで絵文字を含む文字列をクリップボードにコピーする

WSLからWindowsのクリップボードにコピーする方法を試行錯誤したのでまとめ。

結論

alias pbcopy="iconv -t utf16 | tail -c +3 | clip.exe"

もしくは

alias pbcopy="powershell.exe -command '[Console]::InputEncoding = [System.Text.Encoding]::UTF8; \$reader = [System.IO.StreamReader]::new([System.IO.Stream]::Synchronized([System.Console]::OpenStandardInput())); \$reader.ReadToEnd() | Set-Clipboard'"

過程

clip.exe を使う方法

clip.exe

検索して最初に出てくる方法。 最も簡単だが、日本語が文字化けする。

iconv -t sjis | clip.exe

日本語は問題ないが、 のような拡張文字が文字化けする。

iconv -t cp932 | clip.exe

日本語も拡張文字も問題ないが、絵文字が含まれるとエラーになる。

iconv -t utf16 | clip.exe

日本語、拡張文字、絵文字すべてコピーできるが、先頭に BOM (U+FEFF) が付与されてしまう。

iconv -t utf16 | tail -c +3 | clip.exe

BOMを除くことで解決。

Powershellの Set-Clipboard を使う方法

powershell.exe -command 'Read-Host | Set-Clipboard'

日本語が文字化けする。

powershell.exe -command '[Console]::InputEncoding = [System.Text.Encoding]::UTF8; Read-Host | Set-Clipboard'

日本語、拡張文字、絵文字すべてコピーできるが、改行が含まれると1行目しかコピーされない。

powershell.exe -command '[Console]::InputEncoding = [System.Text.Encoding]::UTF8; $reader = [System.IO.StreamReader]::new([System.IO.Stream]::Synchronized([System.Console]::OpenStandardInput())); $reader.ReadToEnd() | Set-Clipboard'

改行も含めて解決。

なお、「結論」で $ をエスケープしているのはシェルの変数として展開されないようにするため。 したがって、

alias pbcopy='powershell.exe -command '\''[Console]::InputEncoding = [System.Text.Encoding]::UTF8; $reader = [System.IO.StreamReader]::new([System.IO.Stream]::Synchronized([System.Console]::OpenStandardInput())); $reader.ReadToEnd() | Set-Clipboard'\'

としても良い。

クリップボードからの出力

クリップボードからの出力は clip.exe ではできないので、Powershellの Get-Clipboard を使う。

alias pbpaste="powershell.exe -command '[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Clipboard'"