zshで直前に実行したコマンドをクリップボードにコピーする

前提としてoh-my-zsh*1を利用。

モチベーション

作業ログを書いている際にコマンドをコピーしたい場面がある。今まではマウスで選択して右クリックでコピーをしていたが自動化チャンスだと思ったのでやる。

コマンド全体

> echo `history -1` | cut -f 2- -d " " | pbcopy

アプローチ

zshのコマンドの履歴は ~/.zsh_history に保存されているので覗いてみる。

> cat ~/.zsh_history | head -n 5
: 1661521409:0;ls
: 1661521409:0;gs
: 1661521409:0;cd contrail
: 1661521409:0;cd generated
: 1661521409:0;cd ..

適当に文字列いじれば取れるけど他に無いかなと探していると、oh-my-zshhistory コマンド*2なるものがあることを見つけた。

> history | head -n 5
    1  ls
    2  gs
    3  cd contrail
    4  cd generated
    5  cd ..

見た感じ内部で ~/.zsh_history を参照していて中身は同じっぽい。こっちをいじった方がシンプルそう。

…とはいえ簡単にはいかなそう。

> history | head -n 2 
    1  ls
    2  gs

> history | tail -n 2 
 1930  history | head -n 2
 1931  history | head -n 10

行の先頭の番号が持ちうる最大桁数分をスペースで埋めていた。素直に cut -b {バイト数} とかができない。 ~/.zsh_history でいじったほうが良さそう? 見切りをつけるためにもう少し粘る。history コマンドの実行結果を眺める。

> history | tail -n 10
 1932  history | tail -n 2
 1933  history | tail -n 1 | cut -d " "
 1934  history | tail -n 1 | cut -f 1 -d " "
 1935  history | tail -n 1 | cut -f 2 -d " "
 1936  history | head -n 1 | cut -f 2 -d " "
 1937  history | head -n 1 | cut -f 3 -d " "
 1938  history | head -n 1 | cut -f 5 -d " "
 1939  history | head -n 1 | cut -f 4 -d " "
 1940  history | head -n 1
 1941  history | head -n 10

最大桁数が表示される最後の方ならcut -d {デリミタ}が使えそう。

> history | tail -n 5 | cut -f 2 -d " "
1940
1941
1942
1943
1944

使えた。ここの桁数を取ってみる。

> history | tail -n 1 | cut -f 2 -d " "        
1965

> history | tail -n 1 | cut -f 2 -d " " | wc -c
       5

4がほしいところだが5になってしまう、何か混じってる?桁数まで考えるとコマンド全体が長くなってしまう。なるべくシンプルにいきたい。もう少しひねり出す。

少し道を外すが、history コマンドのソースコードを眺めているとheadやtailに渡さなくても数字を渡せば欲しい行数を指定できることに気がついた。

> history -1
 2003  history 1

…いやよく考えたら cut -f {A} -d {デリミタ} でAに渡すものを2以降にできれば解決できないか?ということで、オプションfに 2- を渡すことで解決した。

# 適当なコマンド
> echo "hoge" | sed -e "s/o/e/" | sed -e "s/e/i/g"
higi

# 一つ前に実行したコマンドが表示される
> echo `history -1` | cut -f 2- -d " "            
echo "hoge" | sed -e "s/o/e/" | sed -e "s/e/i/g"

# 一つ前に実行したコマンドをクリップボードにコピー
> echo `history -1` | cut -f 2- -d " " | pbcopy

history -1で渡すと改行コードが入ってしまうのが面倒だったりするのでechoに渡している。

参考