Bash – List Only Successfully Run Commands in History

bashcommand history

I'm wondering if there's a way to use the history command but only list commands that were run successfully. Likewise, would there be a way to list ones that produced errors?

I know each command has an exit status of:

0 – Successful execution of command
1 – Command fails because of an error during expansion or redirection, the exit status is greater than zero.
2 – Incorrect command usage
12 – Command found but not executable
127 – Command not found

and can be checked proceeding the command with echo $?
from: http://www.linuxnix.com/2011/03/find-exit-status-script-command-linux.html

Example:

After running these 4 commands:

ls
help
lss
ls nonexistentfile

I tried testing to print only successful commands (exit status of 0), which should be only 'ls' and 'help':

for j in `history | tail -5 | head -4 | cut -d ' ' -f5-`; do $j > cmd_out; if [[ `echo $?` != 0 ]]; then :; else echo $j | grep -v 'bash'; fi; done; rm cmd_out

This outputs:

ls
help
bash: lss: command not found
ls
bash: nonexistentfile.txt: command not found

This somewhat works, but there are two problems:

  1. For some reason, grep -v 'bash' is not excluding lines containing 'bash', but if I do grep 'bash', it will include only the lines with 'bash', I'm not sure why one works and not the other.
  2. It's separating each line/command by string. The last ls command should be
    ls nonexistentfile, but it's running ls and nonexistentfile as separate commands.

Any idea on what I should adjust in the command, or how to go about doing this?

Best Answer

This was a hack I used once on a shared account to track who did what:

PROMPT_COMMAND="history -a; sed -i '\$s/\$/ \#$NAME/' $HISTFILE; history -r; $PROMPT_COMMAND"

It writes the history before the PROMPT is displayed: in effect, after each command. You could modify this to use save the exit code in the history:

PROMPT_COMMAND="CODE=$?; history -a; sed -i '\$s/\$/ \#\$CODE/' $HISTFILE; history -r; $PROMPT_COMMAND"

This would leave entries in your history like:

$ history 2
 1271  vim .bashrc #0
 1272  history 2

(The last entry will be updated, after the history command exits, so the exit code isn't visible in this output.)

This has the annoying effect that history in your prompt will have the comment:

$ # press up
$ history 2 #0

The comment doesn't affect execution or output usually, but makes editing a pain.

Now you can grep your history to see which codes exited successfully:

history | grep '#0$'
# or grep '#[^0]*$' for unsuccessful commands.
Related Question