Bash History: Remembering what you did and when you did it

history david blackwell
Credit: flickr / David Blackwell

Command history can be very handy for repeating commands that you've used recently, even when you need to modify them in some way before using them again. You can reuse previously entered commands by typing things like !11 (rerun command 11 in your history buffer) or use strings such as ^old^new^ to replace some part of your previous command (maybe a filename or username) before running a command again. But if you're a bash user, you can also use your history file to record the date and time when you used each command. You simply have to specify a format for your command time display using a special variable.

The variable is HISTTIMEFORMAT and the arguments that you would use to specify the date format you want to see are the same arguments that you would use with the date command -- arguments like %m for the month and %T for the time.

Once you configure your HISTTIMEFORMAT variable, the current date and time are included in your history file (.bash_history) and you'll see it displayed when you use the history command. Commands that were entered before you set the variable will be displayed with the date and time of setting it but, of course, there's no way for the system to determine when those commands were entered. Going forward, however, you can see the date/time information and even change the format and see it formatted differently. Notice the change in format -- date and time to time and date -- in the example below.

  980  05/19/15 17:26:03 who
  981  05/19/15 17:26:08 date +%T
  982  05/19/15 17:39:50 history
$ history | tail -5
  980  17:26:03 05/19/15 who
  981  17:26:08 05/19/15 date +%T
  982  17:39:50 05/19/15 history
  983  17:43:32 05/19/15 HISTTIMEFORMAT="%T %D"
  984  17:43:37 05/19/15 history | tail -5

You can see the date/time information in your .bash_history file if you dump the file using a command such as od.

$ od -bc .bash_history | tail -6
   w   d  \n   #   1   4   3   2   0   0   2   9   5   4  \n   o
0045000 144 040 055 142 143 040 056 142 141 163 150 137 150 151 163 164
   d-   b   c.   b   a   s   h   _   h   i   s   t
0045020 157 162 171 012
   o   r   y  \n

As you can see, the format selected about prints the date in month/day/year (2 digit) followed by the time. Options are those used by the date command. I believe that all of these options will work with HISTTIMEFORMAT.

%a     locale's abbreviated weekday name (e.g., Sun)
%A     locale's full weekday name (e.g., Sunday)
%b     locale's abbreviated month name (e.g., Jan)
%B     locale's full month name (e.g., January)
%c     locale's date and time (e.g., Thu Mar  3 23:05:25 2005)
%C     century; like %Y, except omit last two digits (e.g., 21)
%d     day of month (e.g, 01)
%D     date; same as %m/%d/%y
%e     day of month, space padded; same as %_d
%F     full date; same as %Y-%m-%d
%g     last two digits of year of ISO week number (see %G)
%G     year of ISO week number (see %V); normally useful only with %V
%h     same as %b
%H     hour (00..23)
%I     hour (01..12)
%j     day of year (001..366)
%k     hour ( 0..23)
%l     hour ( 1..12)
%m     month (01..12)
%M     minute (00..59)
%n     a newline
%p     locale's equivalent of either AM or PM; blank if not known
%P     like %p, but lower case
%r     localeâs 12-hour clock time (e.g., 11:11:04 PM)
%R     24-hour hour and minute; same as %H:%M
%s     seconds since 1970-01-01 00:00:00 UTC
%S     second (00..60)
%t     a tab
%T     time; same as %H:%M:%S
%u     day of week (1..7); 1 is Monday
%U     week number of year, with Sunday as first day of week (00..53)
%V     ISO week number, with Monday as first day of week (01..53)
%w     day of week (0..6); 0 is Sunday
%W     week number of year, with Monday as first day of week (00..53)
%x     locale's date representation (e.g., 12/31/99)
%X     locale's time representation (e.g., 23:13:48)
%y     last two digits of year (00..99)
%Y     year
%z     +hhmm numeric timezone (e.g., -0400)
%:z    +hh:mm numeric timezone (e.g., -04:00)
%::z   +hh:mm:ss numeric time zone (e.g., -04:00:00)
%:::z  numeric  time  zone  with  :  to necessary precision (e.g., -04,+05:30)
%Z     alphabetic time zone abbreviation (e.g., EDT)

If you won't get any value from knowing the time and date each command was entered, it's clearly better to never set the variable and add bulk to your history file. Unsetting the variable won't make it go away. Deleting your history file and unsetting the variable should work.

While the Korn shell doesn't offer this same feature, you can always insert the date and time between each command in your history file using a command like this:

PS1='$(printf "%(# %D %T )T" | read -s)$ '
Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Must read: 10 new UI features coming to Windows 10