Copying previous commands with fzf and zsh

Sometimes I want to copy a command I previously typed on my shell to the clipboard. It may be for documentation, note taking, writing a script, setting up an Ansible playbook, sending to someone… You name it.

While I could always search the terminal window for it and select it, I have set-up an alias that make things much easier and less error-prone:

alias hy="
fc -ln 0 |
awk '!a[\$0]++' |
fzf --tac --multi --header 'Copy history' |
xsel --clipboard
"

This will perform the task silently. If you want a confirmation message after each copy, a clean way is to convert the alias to a function like this:

hy() {
local -r entry="$(fc -ln 0 | awk '!a[$0]++' | fzf --tac --multi --header 'Copy history')"
[[ -n "$entry" ]] && xsel --clipboard <<< "$entry" >/dev/null && echo "Copied to clipboard." >&2
}

In action

The alias in action.

Typing hy (short for “history yank”) brings fzf with the last commands I typed. I can browse them with the keyboard or use the fuzzy search. Pressing enter will copy the selection to the clipboard.

Better yet, as I have multi-selection enable on fzf, I can select multiple commands using tab. They are copied one per line.

The how

Explaining each part:

  • fc -ln 0: On zsh, this returns the entire shell history, one command per line. If you use Bash or other shell, just replace it with the equivalent command.
  • awk '!a[\$0]++': The history is piped to awk, which removes the duplicates. Without this cleaning, fzf may display multiple repeated lines, which can be annoying.
  • fzf --tac --header 'Copy history': The result is piped to fzf. The --tac argument reverses the order: we want the last commands to be at the top, while --multi allows multiple selection. We also add a prompt message using --header.
  • xsel --clipboard: Finally, the commands we selected are copied to the clipboard by xsel.

Needless to say, be sure to have awk, fzf and xsel installed on your system for this to work.


Updates

  • : Add implementation to print a confirmation message.
  • : Replace xclip with xsel.

  • All posts · Show comments