awk '/^#[0-9]*$/ {split($0, arr, "#"); print "#", strftime("%c", arr[2]); getline; print }' < /path/to/.bash_history
When HISTTIMEFORMAT is set, the command history of a Bash shell will be written to $HISTFILE, with comment lines of the timestamp of the command in epoch format, for example:
#1583857757
history
#1583857774
grep HIST /etc/bashrc
#1583857783
grep HIST /etc/skel/.bash_profile /etc/skel/.bashrc
#1583857945
tail .bash_history
The one-liner converts the epoch dates in this format into human readable dates to look like this:
# Tue 10 Mar 2020 04:29:17 PM UTC
history
# Tue 10 Mar 2020 04:29:34 PM UTC
grep HIST /etc/bashrc
# Tue 10 Mar 2020 04:29:43 PM UTC
grep HIST /etc/skel/.bash_profile /etc/skel/.bashrc
# Tue 10 Mar 2020 04:32:25 PM UTC
tail .bash_history
With awk '...' < /path/to/file we execute Awk commands in ..., using the content of /path/to/file as the input, with the < input redirection operator.
The first part of the Awk command /.../ is a filter: it matches lines in the input with the regular expression in .... The regular expression ^#[0-9]*$ matches lines that start with a "#", followed by zero or more digits until the end of the line.
For the matched pattern, Awk executes all the commands within the following { ... } block.
split($0, arr, "#") splits the line ($0) by #, storing the result in the array variable arrprint "#", strftime("%c", arr[2]) prints a line, starting with #, followed by a space, followed by the value of arr[2] formatted as s human readable time. arr[2] contains the timestamp in epoch format, notice that arrays in Awk use 1 as the starting index. If we take for example the input #123, then arr[1] is the empty string, and arr[2] is 123.strftime("%c", ...) formats a value as a human readable date. See man strftime for other possible formats.getline reads the next line of input and stores in the variable $0print simply prints the content of the variable $0