29

I can see the last command in the terminal by pressing up arrow as in the following example:

I typed cd /:

Makss-Mac:~ maks$ cd /

... pressed enter, command cd / executed and now I can press up arrow and see the command cd / again:

Makss-Mac:/ maks$ cd /

I want to not only see the last command but also copy it to the clipboard.

Maybe there exists a shortcut that not only shows the last command in the terminal (as up arrow does) but at the same time copies it to the clipboard.

Or maybe there is a shortcut for selecting all from current terminal line. And so I would be able to copy the last command (after pressing up arrow) by pressing super+c. Of course I can select it with the mouse. But when commands are 10 times longer than cd / it can be too time-consuming, especially if you do it every 30 seconds.

Or is there maybe a way to write a plugin for the terminal?

2
  • It might be easier to find a solution here if you could add some details about what you intend to do with the content of the clipboard afterwards. Where are you going to paste it to?
    – nohillside
    Nov 12, 2013 at 18:40
  • yes to paste it to another terminal tab Nov 13, 2013 at 3:28

5 Answers 5

28

Put this into your ~/.bashrc ~/.bash_profile or where-ever you like it:

alias copyLastCmd='fc -ln -1 | awk '{$1=$1}1' | pbcopy '

After opening a new window (or running source ~/.bash_profile) you should be able to run copyLastCmd and have the command in the clipboard.

To explain what's going on: you're basically using "fix command" (fc) to get you the last command, remove both leading and trailing whitespace for nicer formatting with awk and then copy it into your Mac's pasteboard with pbcopy.

EDIT:

Now that we know that you want to copy to paste into another terminal tab, there's another option: Add these lines to your ~/.bashrc ~/.bash_profile or where-ever you like it:

shopt -s histappend
PROMPT_COMMAND='$PROMPT_COMMAND; history -a; history -n'

Then, once you have some new tabs open (let's call them "tab A" and "tab B"):

  1. Execute any command in tab A
  2. Switch to tab B, press enter on an empty line, giving you a "fresh" new line (and thus re-evaluating the history)
  3. use the up arrow once and you should have the command you've just entered in tab A.

EDIT 2: I've replaced the usage of sed with awk in the original answer above, to take care of both leading and trailing whitespace .

9
  • That's a great alias! To cut off the trailing new line, so you can edit the command after pasting, I used awk: alias copyLastCmd='fc -ln -1 | sed '1s/^[[:space:]]*//' | awk 1 ORS="" | pbcopy '
    – nwinkler
    Nov 13, 2013 at 14:48
  • @nwinkler: OH you're right, should've used awk: fc -ln -1 | awk '{$1=$1}1' will remove both trailing and leading whitespace.
    – Asmus
    Nov 13, 2013 at 15:09
  • 2
    had to modify the alias for special chars alias copyLastCmd="fc -ln -1 | awk '{\$1=\$1}1' | pbcopy". still gets my upvote
    – Mike D
    Apr 8, 2016 at 12:29
  • 1
    I used this until I did a "git -reset --hard" on one terminal and in another "unsuspecting git folder" pressed up arrow and enter hastily as I thought I was running a script I was using before. You can imagine what happened, and that was the last time I used this shared "global" history
    – MrGigu
    Dec 5, 2017 at 7:08
  • @MrGigu happened to me with a "local" history where I pressed the "up" arrow twice, instead of once, accidentally - lessons learned the hard way, I guess.
    – Asmus
    Dec 5, 2017 at 12:15
14

This will use history expansion to grab the last command and echo it. You can pipe to pbcopy to save the last command to your clipboard.

> echo !! | pbcopy

If you want a command from your history that was not the last one, you can run:

> history

And reference the desired command number like:

> echo !5 | pbcopy
3
  • 1
    It may be your favorite, and it may even work, but you need to supply a little explication about what the command actually does, and how the OP (who accepted one of the answers five years ago) can use it effectively.
    – IconDaemon
    Dec 7, 2018 at 15:30
  • @IconDaemon good call. I think this is worth adding to an old question because it is simpler than the accepted answer since it does not require any profile customization.
    – Sam Berry
    Dec 7, 2018 at 15:47
  • If you want the second to last command: echo !-2 | pbcopy. Jul 4 at 17:55
9

Here's another take based on the answer by @Asmus. To make his alias work in my bash script, I had to use a bit of quoting, since single quotes don't work in a single-quoted alias without some additional quoting:

alias copyLastCmd='fc -ln -1 | awk '\''{$1=$1}1'\'' | pbcopy'

The '\'' will basically close the current quote, then add an escaped quote, and then open the actual quote again.

The above version will copy the last command to your clipboard, and once you paste it, it's immediately executed, since it will have a newline at the end.

To get rid of the newline at the end, so you can actually edit the command before running it, you can do the following:

alias copyLastCmd='fc -ln -1 | awk '\''{$1=$1}1'\'' ORS='\'''\'' | pbcopy'

The ORS='' (that's without the quoting) will strip off the trailing newline character, so you can edit the pasted text before running it.

1
  • Thank you for this - none of the above solutions worked for me. You've helped me save a lot of time. Feb 18, 2022 at 21:39
8

I came here as came up with Sam Berry's exact same answer, but it doesn't work for me (OSX 10.14.6).

Managed to get it to do so with quotes around the !! :

echo "!!" | pbcopy

3

You can set your history to ignore commands that start with a space:

export HISTIGNORE=' *'

And then run the following command to git the last command to the clipboard (make sure you have a space at the beginning):

history 1 | cut -d " " -f 4- | pbcopy

You probably would then want to save the command as an alias to make it easier to remember.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .