'Copy current command at bash prompt to clipboard

I would like a quick keyboard command sequence to copy the current command at a bash prompt to the clipboard.

So that, for example, to copy the last bash command to the clipboard, I'd press up+[some command sequence] to copy it. Or, for example, to search for a command in bash hisory, I'd use ctrl+r, search, display it on the command prompt, and then [some command sequence] to copy it, etc.

My current solution is using bash pipes: Pipe to/from the clipboard

So, to copy the previous command to clipboard:

echo "!!" | pbcopy

Which isn't too terrible, but what if the command to copy isn't the last command, etc.

What's the proper way to achieve what I'm trying to achieve here?



Solution 1:[1]

Taking @Lauri's post for inspiration, here's a solution using the bind command:

bind '"\C-]":"\C-e\C-u pbcopy <<"EOF"\n\C-y\nEOF\n"'

ctrl-] then will copy whatever is on the current bash prompt to the clipboard.

To make it persistent, you can add the bind command as above to your ~/.bashrc, or you can strip off the outer quotes and remove the 'bind' part of the call and add the result to your ~/.inputrc.

Non-OS-X users will have to swap pbcopy out with the appropriate command, probably xclip.

A quoted heredoc was used instead of a an echo+pipe technique so that both single and double quotes in the command at the bash prompt are preserved. With this technique, for example, I was able to hit ctrl-], copy the actual bind command from the terminal prompt, and paste it here in the answer. So the heredoc technique handles all of the special characters in the bind command here.

Solution 2:[2]

You can use READLINE_LINE with bind -x in bash 4:

copyline() { printf %s "$READLINE_LINE"|pbcopy; }
bind -x '"\C-xc":copyline'

You can install bash 4 and make it the default login shell by running brew install bash;echo /usr/local/bin/bash|sudo tee -a /etc/shells;chsh -s /usr/local/bin/bash.

I also use this function to copy the last command:

cl() { history -p '!!'|tr -d \\n|pbcopy; }

Solution 3:[3]

I spent a decent amount of time today writing a simple zsh implementation for macOS; usage is as follows:

example command:          git commit -m "Changed a few things"
command that copies:      c git commit -m "Changed a few things"

# The second command does not actually execute the command, it just copies it. 

# Using zsh, this should reduce the whole process to about 3 keystrokes:
#
# 1) CTRL + A (to go to the beginning of the line) 
# 2) 'c' + ' '
# 3) ENTER

preexec() is a zsh hook function that gets called right when you press enter, but before the command actually executes.

Since zsh strips arguments of certain characters like ' " ', we will want to use preexec(), which allows you to access the unprocessed, original command.

Pseudocode goes like this:

1) Make sure the command has 'c ' in the beginning

2) If it does, copy the whole command, char by char, to a temp variable

3) Pipe the temp variable into pbcopy, macOS's copy buffer

Real code:

c() {} # you'll want this so that you don't get a command unrecognized error

preexec() {
  tmp="";
  if [ "${1:0:1}" = "c" ] && [ "${1:1:1}" = " " ] && [ "${1:2:1}" != " " ]; then                                  
    for (( i=2; i<${#1}; i++ )); do
      tmp="${tmp}${1:$i:1}";  
    done
    echo "$tmp" | pbcopy;
  fi
}

Go ahead and stick the two aforementioned functions in your .zshrc file, or wherever you want (I put mine in a file in my .oh-my-zsh/custom directory).

If anyone has a more elegant solution, plz speak up. Anything to avoid using the mouse.

Solution 4:[4]

If xsel is installed on your system you can add this in .inputrc :

C-]: '\C-e\C-ucat <<"EOF" | tr -d "\\n" | xsel -ib\n\C-y\nEOF\n'

Alternatively, if xclip is installed you could add this:

C-]: '\C-e\C-ucat <<"EOF" | tr -d "\\n" | xclip -se c\n\C-y\nEOF\n'

Notice: Used code from @Clayton's answer.

Solution 5:[5]

I use history to find the command number that I am looking for, then I do:

echo "!command_number" | xclip -in

Solution 6:[6]

$ history | cut -c 8- | tail -1 | pbcopy

or in .zshrc file add an alias

alias copy='history | cut -c 8- | tail -1 | pbcopy'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Lri
Solution 3
Solution 4 Addison
Solution 5 Stephen Rauch
Solution 6 Deepak Dubey