I've configured Bash to save multiline history entries with embedded newlines.
shopt -s cmdhist lithist
export HISTTIMEFORMAT='%F %T '
When I exit the shell, my history is appended to ~/.bash_history
with timestamps separating the entries, like:
#1501293767
foo() {
echo foo
}
#1501293785
ls
I experimented with setting HISTIGNORE
to filter out some commands,
HISTIGNORE='ls[ ]*:man[ ]*:cat[ ]*'
but quickly realized I prefer to include everything in the current session's (in memory) history, I just want to filter what gets written to disk for future sessions.
I'd like to leverage ~/.bash_logout
to do this filtering (I've been looking at these answers to a couple related questions).
The multiline entries make filtering a little complicated. I need to identify entries where the first line following the timestamp matches one of the ignorable patterns, and exclude the entire entry, including the timestamp.
I've come up with a way to do this with awk, but my awk skills are not great, so I wonder if there's a better way?
filter_history() {
tmpfile=$(mktemp)
history -w $tmpfile
awk '/^#[[:digit:]]{10}$/ { timestamp=$0; ignore=0; next }
length(timestamp) > 0 && /^(ls|man|cat)([^[:alnum:]]|$)/ { timestamp=""; ignore=1 ; next }
length(timestamp) > 0 { print timestamp; timestamp=""; print; next }
ignore == 0 { print }' \
$tmpfile >> $HISTFILE && rm $tmpfile
}
Edit: Actually, I can't think of a case where I'd want to filter out a multi-line entry. Even if it starts with ls
, for instance, if it span multiple lines it's probably doing something interesting, and worth remembering.
.bash_logout
is only executed in a login shell, it isn't useful here. Run this code from an exit trap instead (trap filter_history EXIT
).EXIT
causes my filter to run too late, i.e. after the history has already been written to disk. I could adjust my script to filter the entire contents of HISTFILE after the fact, but it seems smarter to filter incrementally, i.e. just the contents I want appended to the existing file. Maybe I should trapSIGHUP
and unset HISTFILE after manually appending to it?