I'm looking for a nuanced history behavior I haven't seen anywhere.
- During a terminal session, I want every command, regardless of exit status, to be appended to the in-memory history.
- Upon exiting the session, when the in-memory history is written to disk at
~/.bash_history, I want to omit commands that failed.
Hopefully the reasoning is clear: within a session, one of the most common uses of history is to re-attempt the last (failed) command, either with a minor edit, or after changing some environmental fact in the hopes of getting better results.
But, at the same time, I don't want my long-term history to be littered with bad commands.
I've seen this post, which shows how to (1) determine the exit status of the last command, and (2) how to remove history entries by index.
And I've seen this answer, which shows how to use
trap to execute commands when a session ends.
(I've also studied this mega-answer, which seems to cover a lot of quirks having to do with history manipulation. Although I'm not sure how relevant it is.)
I have a rough idea of how I might accomplish my goal, but I'm not very experienced with bash programming, and I'm having trouble cashing it out. My plan:
- I create a new file,
$TEMP/.bash_history_failures_IDENTIFIERfor each terminal session, replacing
IDENTIFIERwith some kind of session-specific value (PID?) that guarantees multiple sessions don't clobber each other
- using a combination of
[ $exit_status -eq 127 ], I write the index of each bad command to the current session's failures file
- using the
traphook to execute code on exit, I invoke a function that iterates through the indexes in this session's failures file, doing
history -d $numberon each entry
- finally, I let the remains of in-memory history (which should be all and only successful commands) be written to
~/.bash_historyin accordance with whatever are my
Is what I'm proposing possible? What am I overlooking? Will I run into problems deleting items from history in ascending order? What's a good, stable way of creating a unique file for each session?
What do I consider a "failed" command?
I don't want long-term history to contain user-errors:
- commands that don't exist
- syntax errors
I want to keep commands that are correct, even if they were unable to execute for some other reason (e.g. inadequate permissions, non-existent input paths).
The two examples that come to mind are that I constantly forget where to insert the semicolons in one-liners like this:
for pkg in $(ls ./packages); do cp ./.eslintrc.yml ./packages/$pkg/; done
I don't want history to contain the entries where I put the semis in the wrong place.
The other case is that it usually takes me several attempts to come up with the correct options for
cut, and most of my mistakes are syntax errors in specifying the arguments to it.
I'd love it if my long-term bash history could omit the many failed attempts at getting working commands right. I'm not concerned about history containing e.g. searches that happen to produce no results.