You could do something like:
fixhist() {
local cmd histnum
cmd=$(HISTTIMEFORMAT=/ history 1)
histnum=$((${cmd%%[*/]*}))
cmd=${cmd#*/} # remove the histnum
case $cmd in
(rm\ *|mv\ *|...)
history -d "$histnum" # delete
history -s "#$cmd" # add back with a #
esac
}
PROMPT_COMMAND=fixhist
The idea being that before each prompt, we check the last history entry (history 1
) and if it's one of the dangerous ones, we delete it (history -d
) and add it back with a #
with history -s
.
(obviously, you need to remove your HISTIGNORE
setting).
An unwanted side effect of that though is that it alters the history time of those rm
, mv
... commands.
To fix that, an alternative could be:
fixhist() {
local cmd time histnum
cmd=$(HISTTIMEFORMAT='<%s>' history 1)
histnum=$((${cmd%%[<*]*}))
time=${cmd%%>*}
time=${time#*<}
cmd=${cmd#*>}
case $cmd in
(rm\ *|mv\ *|...)
history -d "$histnum" # delete
HISTFILE=/dev/stdin history -r <<EOF
#$time
#$cmd
EOF
esac
}
PROMPT_COMMAND=fixhist
This time, we record the time of the last history, and to add back the history line, we use history -r
from a temporary file (the here document) that includes the timestamp.
You'd want the fixhist
to be performed before your history -a; history -c; history -r
. Unfortunately, the current version of bash
has a bug in that history -a
doesn't save that extra line that we've added. A work around is to write it instead:
fixhist() {
local cmd time histnum
cmd=$(HISTTIMEFORMAT='<%s>' history 1)
histnum=$((${cmd%%[<*]*}))
time=${cmd%%>*}
time=${time#*<}
cmd=${cmd#*>}
case $cmd in
(rm\ *|mv\ *|...)
history -d "$histnum" # delete
history -a
[ -f "$HISTFILE" ] && printf '#%s\n' "$time" "$cmd" >> "$HISTFILE";;
(*)
history -a
esac
history -c
history -r
}
PROMPT_COMMAND=fixhist
That is to append the commented command to the HISTFILE ourselves instead of letting history -a
do it.
Best Answer
As @Jesse_b commented,
.bash_history
contains the history of all your previous shell sessions except the current one, which can be examined via thehistory
command. So you'll have first to flush the current history viaand then you can copy it to another file:
To prepend each history entry with a timestamp, set the $HISTTIMEFORMAT variable, e.g.