389

Is there any way I can see at what time the commands were executed from the bash history? We can see the order but is there any way I can get the time also?

Bottom-Line: Execution time in the Bash history

6
  • 9
    I'm amazed how poorly documented this is both on Linux and BSD in the manpages. Commented Aug 30, 2016 at 21:52
  • Check this blog out - sanctum.geek.nz/arabesque/better-bash-history .
    – lightsong
    Commented Feb 22, 2018 at 10:31
  • 22
    if you're using zsh: history -E
    – Vahid
    Commented Nov 6, 2018 at 16:58
  • 10
    Not sure why two answers below feel the need to tell you how to open a terminal..
    – mwfearnley
    Commented Dec 24, 2018 at 8:39
  • 4
    According to the blog referenced by @dog0 , timestampse apparently do not get saved unless the HISTTIMEFORMAT variable was set when commands were issued. In other words, if you didn't have it set, setting it now will not help you retrieve timestamps of previously issued commands. Commented Jan 17, 2019 at 15:14

9 Answers 9

474

Press Ctrl+Alt+T to open a terminal, then run one of the commands below:

HISTTIMEFORMAT="%d/%m/%y %T "  # for e.g. “29/02/99 23:59:59”
HISTTIMEFORMAT="%F %T "        # for e.g. “1999-02-29 23:59:59”

To make the change permanent for the current user run:

echo 'HISTTIMEFORMAT="%d/%m/%y %T "' >> ~/.bashrc  # or respectively
echo 'HISTTIMEFORMAT="%F %T "' >> ~/.bashrc
source ~/.bashrc

To test the effects run:

history

For more info see man bash or An A-Z Index of the Bash command line for Linux.

For commands that were run before HISTTIMEFORMAT was set, the current time will be saved as the timestamp. Commands run after HISTTIMEFORMAT was set will have the proper timestamp saved.

10
  • 113
    Note that this will only record timestamps for new history items, after HISTTIMEFORMAT is set for sessions, i.e. you can't use this retrospectively. Some answers here give the impression the history command immediately shows timestamped entries Commented Feb 20, 2016 at 20:58
  • 21
    @Jamil: for people who follow ISO standards, it's "%y-%m-%d" for the date part ;)
    – Gauthier
    Commented Mar 31, 2016 at 11:03
  • 4
    Just a note to zsh users out there - unlike many builtins it does not mirror bash. See this instead: unix.stackexchange.com/questions/103398/… Commented Aug 30, 2016 at 21:59
  • 15
    @Gauthier - actually, just use %F for ISO date ;-) man7.org/linux/man-pages/man3/strftime.3.html Commented Jul 11, 2018 at 19:34
  • 8
    Weirdly, this did appear to work for me retrospectively - I was able to see the timestamps of history items prior to my explicit setting of this environment variable. That may be because HISTTIMEFORMAT was set to an empty string before, or something similar?
    – ijoseph
    Commented Oct 28, 2020 at 17:22
105

Open terminalCtrl+Alt+T and run,

HISTTIMEFORMAT="%d/%m/%y %T "

then,

history

To make the changes permanent follow the below steps,

gedit ~/.bashrc

you need to add the below line to .bashrc file and then save it,

export HISTTIMEFORMAT="%d/%m/%y %T "

run the below command to source .bashrc file,

source ~/.bashrc

After that run history command.

enter image description here

source:http://www.cyberciti.biz/faq/unix-linux-bash-history-display-date-time/

3
  • Thanks for answering , \will it be permanent change ?
    – Raja G
    Commented Dec 15, 2013 at 12:06
  • 1
    Hey, I'm doing this in OS X and Windows (through MINGW), and I'm adding it into .bash_profile, what's the diff between profile and rc? Commented Oct 1, 2015 at 17:28
  • 1
    HISTTIMEFORMAT="%d/%m/%y %T " history works
    – Alex78191
    Commented Mar 25, 2020 at 11:06
25

Yes, you can: if you set $HISTTIMEFORMAT, the .bash-history will be properly timestamped. That doesn't help with existing .bash-history content, but will help in the future.

4
  • 1
    can you expand it for more clarity ?
    – Raja G
    Commented Dec 15, 2013 at 12:06
  • 6
    Correction to previous post: Setting HISTTIMEFORMAT enables the display of the timestamps...even existing. My favorite is:HISTTIMEFORMAT='%F %T ' as it matters not from which country you reside...everyone knows immediately what time it is. :)
    – user491029
    Commented Jan 8, 2016 at 22:43
  • 5
    I set $HISTTIMEFORMAT and I got the times for today even before the commands of this set. Commented Sep 18, 2017 at 13:40
  • 3
    @user491029 "...even existing". This is true, but misleading. On ubuntu 14.04, at least, it did start showing timestamps for all history entries once I had set HISTTIMEFORMAT, but it looks like the timestamps for any command run before the current session were the login timestamp of the current session.
    – jbobbins
    Commented Jun 27, 2019 at 19:52
17

Changing HISTIMEFORMAT didn't work for me, because I'm using zsh.

If you want to make it work with zsh, you just have to type : history -i

1
  • 5
    zsh: 1, bash: 0
    – Mark
    Commented Feb 27, 2022 at 22:22
3

My version that works

HISTTIMEFORMAT="%F %T %z " history | grep 'your command'

ref. https://www.linuxuprising.com/2019/07/bash-history-how-to-show-timestamp-when.html

E.g.

╭you@your-server:/some/path 
╰$ HISTTIMEFORMAT="%F %T %z "; history | grep 'some command'
 1947  2019-12-17 15:54:34 +0800 ./some.sh
 1948  2019-12-17 15:54:34 +0800 ./my-command

View full syntax for HISTTIMEFORMAT here

3

You 'll see changes on next login.

echo 'HISTTIMEFORMAT="%d/%m/%y %T "' >> ~/.bashrc
2

To enable history timestamps for all users, create a script in /etc/profile.d :

echo 'HISTTIMEFORMAT="%Y%m%d %T "' >> /etc/profile.d/timestamp.sh
2
  • 3
    This will likely not work for users logging in via the GUI, since the default terminal will not run login shells. /etc/bash.bashrc would be a better place.
    – muru
    Commented Feb 22, 2018 at 10:12
  • Make sure permission of /etc/profile.d/timestamp.sh is '644' , so that history command shows timestamp for all users .
    – sjethvani
    Commented Aug 20, 2020 at 13:29
1

I maintain a history per tty device per user, in .bash_profile, and let them grow large. Sometimes I want to find where a command was used across all those files using grep, say. I have just spent a while getting how I want, with time stamps as strings and headers for each file plus which tty before the time so if I am grepping I will see where and when used:

$ awk 'BEGIN{RS="#"; FS="\n"} {if (FNR == 1){ print "\n==>" FILENAME "<=="; tty=substr(FILENAME,15,9) }; if ((ln==0) && ($1 ~/^[0-9]+$/)){Cmd="date -r "$1""; Cmd | getline textDate; close(Cmd);baseD=substr(textDate,1,length(textDate)-5);baseS=$1}; if ($1 ~/^[0-9]+$/){printf "%s %s+%.2fH (%d)%s\n",  tty, baseD, ($1-baseS)/3600, $1, $2; if (ln==0) {ln=20} else {ln--}}} ' .bash_history_ttys003|head

==>.bash_history_ttys003<==
ttys003 Thu 28 Sep 2017 10:45:48+0.00H (1506591948)cp Qlog t
ttys003 Thu 28 Sep 2017 10:45:48+6.12H (1506613974)grep \ 755\  Qlog
ttys003 Thu 28 Sep 2017 10:45:48+6.15H (1506614092)grep \ 769\  Qlog
ttys003 Thu 28 Sep 2017 10:45:48+6.16H (1506614130)locate akd
ttys003 Thu 28 Sep 2017 10:45:48+6.17H (1506614159)less /System/Library/LaunchAgents/com.apple.akd.plist
ttys003 Thu 28 Sep 2017 10:45:48+6.17H (1506614172)mN -K PLIST
ttys003 Thu 28 Sep 2017 10:45:48+6.18H (1506614179)man -k plist
ttys003 Thu 28 Sep 2017 10:45:48+6.18H (1506614213)man swapllist

Can't go into all the background as life is too short (LITS) but here are my dev notes as I worked it up. This is on macOS so no special gawk but I do use date -r where it may differ for you, date -d?. Enjoy! :

How would I list all .bash_history* lines that grep finds together with the Unix timestamp as string?
sample data lines in history (#unix time \n command)
head .bash_history_ttys007
\#1502956374
man top
\#1502956600
top

As 2 lines looks like an awk task...
Can't print FILENAME in begin as there is no current file at that stage :( so use FNR file rec numb check...
awk 'BEGIN{RS="#"} {if (FNR == 1){ print FILENAME }; "date -r "$1"" | getline textDate; close(date);print textDate, $0}'
awk 'BEGIN{RS="#"} {if (FNR == 1){ print FILENAME }; "date -r "$1"" | getline textDate; close(date);print textDate, $0}' .bash_history_ttys00[67]|head
Works but 3 lines per item as x0a line-returns are in there. WILL HAVE OTHER PROBLEMS TOO (later)...
Progress by field sep on new lines and carve up filename for controlling terminal
awk 'BEGIN{RS="#"; FS="\n"} {if (FNR == 1){ print "\n==>" FILENAME "<=="; tty=substr(FILENAME,15,9) }; if ($1 ~/^[0-9]+$/){"date -r "$1"" | getline textDate; close(date);print  tty, substr(textDate,1,length(textDate)-1) ,"(" $1")", $2} }' .bash_history_ttys00[67]|head

$ awk 'BEGIN{RS="#"; FS="\n"} {if (FNR == 1){ print "\n==>" FILENAME "<=="; tty=substr(FILENAME,15,9) }; if ($1 ~/^[0-9]+$/){"date -r "$1"" | getline textDate; close(date -r "$1");print  tty, substr(textDate,1,length(textDate)-1) ,"(" $1")", $2} }' .bash_history_ttys002

Works OK but runs a bit slow: just do dates every once in a while? then if grep-ing will probably miss it...
awk 'BEGIN{RS="#"; FS="\n"} {if (FNR == 1){ print "\n==>" FILENAME "<=="; tty=substr(FILENAME,15,9) }; if ($1 ~/^[0-9]+$/){Cmd="date -r "$1""; Cmd | getline textDate; close(Cmd);print  tty, substr(textDate,1,length(textDate)-1) ,"(" $1")", $2} }' .bash_history_ttys002

Do occasional date convert and retain string and offset secs? this does run much faster and requires timestamps to avoid # in commands. About 5s for 20,000 commands for me.
awk 'BEGIN{RS="#"; FS="\n"} {if (FNR == 1){ print "\n==>" FILENAME "<=="; tty=substr(FILENAME,15,9) }; if ((ln==0) && ($1 ~/^[0-9]+$/)){Cmd="date -r "$1""; Cmd | getline textDate; close(Cmd);baseD=substr(textDate,1,length(textDate)-5);baseS=$1}; if ($1 ~/^[0-9]+$/){printf "%s %s+%.2fH (%d)%s\n",  tty, baseD, ($1-baseS)/3600, $1, $2; if (ln==0) {ln=20} else {ln--}}} ' .bash_history_ttys003
0

I know, I'm answering it very late, but to do this for all the users, you can create any .sh file in /etc/profile.d and add the following line to it:

echo 'HISTTIMEFORMAT="%Y-%m-%d %T "' >> /etc/profile.d/existing-foo-file.sh

If you not logged in as root or superuser, you need to use the tee command to do this:

echo 'HISTTIMEFORMAT="%Y-%m-%d %T "' | sudo tee /etc/profile.d/mytimestamp.sh

If you want to append to any existing file, pass -a flag to tee command:

echo 'HISTTIMEFORMAT="%Y-%m-%d %T "' | sudo tee -a /etc/profile.d/mytimestamp.sh

enter image description here

4
  • Hello Shashank, Thanks for adding the answer but how this answer is different from others ? If your answer is completely different then we are glad to have it, but if not you can improve existing answers.
    – Raja G
    Commented Jul 22, 2019 at 5:03
  • 1
    Hi, thanks for commenting. This is different from others in the following way: 1. Some of them have mentioned about creating for all users but no one mentioned about creating/explaining any file name in /etc/profile.d. timestamp.sh looks very close to technical (so it creates confusion) so I used the name existing-foo-file.sh (foo-bar concept). 2. No one has mentioned about using it with non-root users. So I have given an example of using sudo. 3. The 3rd example improves the 2nd example of appending to an existing file. Since linux/unix beginners can hit this issue, I elaborated. Commented Jul 22, 2019 at 5:32
  • 1
    Just a note : Make sure permission of /etc/profile.d/timestamp.sh is '644' , so that history command shows timestamp for all users . In my case permission of '/etc/profile.d/timestamp.sh' was '640' , because of which users other than owner was not seeing timeformatted history .
    – sjethvani
    Commented Aug 20, 2020 at 13:38
  • Thanks @sjethvani Commented Aug 20, 2020 at 13:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .