Get the nth last command

From raju

Situation

While working on a complex task, I often end up with a command which I like to store for future reference. The idea is to do this in a seamless way.

Solution

Add this function to ~/.zshrc

    getlast() {
        if [ -z "$1" ]; then
            fc -ln -1
        else
            fc -ln -"$1" -"$1"
        fi
    }
    

Then to get the nth last command, simply do

  getlast n

For example, to get the last but one command and append it to a file, do

  getlast 2 >> log.txt

To get the last command, use

 getlast 1

or simply

 getlast

How it works

fc stands for "fix command". It is a shell builtin provided by most modern shells such as zsh and bash. It is used to make small changes to a previous command and execute it.

With the -l option, fc just prints the command instead of bringing it up in an editor. The -n option suppresses the command numbers when listing. The range of commands is specified in the third and fourth arguments respectively. If the range contains negative numbers, the commands are looked up from the bottom of the history (i.e. most recent commands). See "man fc" for all the juicy details.

Limitations

  • Works in bash, zsh where the fc builtin is available. Does not work in tcsh.

Related links

  • "man fc" and then search for fc
  • http://unix.stackexchange.com/questions/38072/how-can-i-save-the-last-command-to-a-file - contains useful discussion. I borrowed the original code from here and modified it to fit my needs.
  • https://gitlab.com/d3k2mk7/dotfiles/blob/master/zsh/zshrc - my zshrc file.

Alternative approaches

  • copy paste the command using mouse. But this may involve opening a new editor, switching windows, moving hand between keyboard and mouse etc., All these additional steps can distract from the original task.
  • Echo the previous command after enclosing it in brackets and append it to a file. This involves a lot of unnecessary and complex keystrokes. For example
up arrow -> <CTRL-a> -> echo " -> <END> -> " >> log.txt
  • echo "!!" >> log.txt

This can break for complex commands. For example,

$ "ls" | less
$ echo "!!" >> log.txt
$ cat log.txt
ls | less

Moreover, if you do <UP> arrow again, it will show the "echo" command which may not always be desirable.