Unable to read the timestamp of Zsh history

Converting timestamps with awk

If you want to read the file itself, to use with, say, grep or any other filter, you need to convert timestamps.

I made this script, which I save it in my /usr/local/bin, and it works for bash and zshell:

Script uhistory.awk at /usr/local/bin/uhistory.awk

#!/usr/bin/awk -f
{ 
        if (match($0,/^#/)) # bash
        {
                nlin++
                #adata="@"substr($0,2) 
                #printf("%s ", adata)
                cmdata = "date -d \"@" substr($0,2) "\" +\"%F %H:%M:%S\"" 
                cmdata | getline datado
                close(cmdata)
                printf("%d %s ", nlin, datado)
        }
        else
        if (match($0,/^:/)) # zshell
        {
            nlin++
            split($0, arr, ":|;")
            cmdata = "date -d \"@" substr(arr[2],2) "\" +\"%F %H:%M:%S\"" 
            cmdata | getline datado
            close(cmdata)
            printf("%d : %s ; %ss % ", nlin, datado, arr[3])
            for (i in arr)
            {
                if (i < 4)
                    continue
                printf("%s ", arr[i])
            }
            printf("\n")
        }
        else
        {
            print $0
        }
}

Usage: you can pipe the history through the filter. Suppose the history file for zsh, that has the format:

:timestamp:duration;commands

Without the uhistory.awk filter would be:

% head ~/.config/zsh/zhistfile

: 1570482839:0;la
: 1570482839:0;cd zsh
: 1570482839:0;ls
: 1570482839:1;cat verybigaliasfile.txt
: 1570482839:0;alias
: 1570482839:0;ls -la
: 1570482839:0;vi .zshrc
: 1570482839:0;alias

With the uhistory.awk filter, it would show as:

% head ~/.config/zsh/zhistfile | uhistory.awk | grep alias

4 : 2019-10-07 18:13:59 ; 1s % cat verybigaliasfile.txt
5 : 2019-10-07 18:13:59 ; 0s % alias 
9 : 2019-10-07 18:13:59 ; 0s % alias 

But if your usage doesn't involve treating the file itself, all you really need is just an alias.

Add this line to your .zsh_aliases or some other place you have for your aliases.

alias history='fc -il 1'

or some other option from fc command. Check with man zshbuiltins


Even better is to use the same command, so it is not confusing in case you want to add another key/option at the end. In this case I recommand:

alias history='history -i'

And of course you can just pipe the result, for example:

% history | grep alias

4   2019-10-07 18:13:59  cat verybigaliasfile.txt
5   2019-10-07 18:13:59  alias 
9   2019-10-07 18:13:59  alias 

In this case, duration won't appear, but the rest is the same.


Try history -d. Or just type history - and press control-D to get all the various options:

% history -
-D  -- print elapsed times
-E  -- dd.mm.yyyy format time-stamps
-d  -- print time-stamps
-f  -- mm/dd/yyyy format time-stamps
-i  -- yyyy-mm-dd format time-stamps
-m  -- treat first argument as a pattern
-n  -- suppress line numbers
-r  -- reverse order of the commands

This simple util, called localtime is gold for reading files with timestamps:

#!/usr/bin/perl
# http://perl.plover.com/classes/mybin/samples/source/localtime

if ($ARGV[0] eq '-f') {
  *show_localtime = \&show_localtime_list;
  shift;
}

if (@ARGV) {
  for (@ARGV) {
    print show_localtime($_), "\n";
  }
} else {
  while (<>) {
    s/^(\d+)/show_localtime($1)/e;
    print;
  }
}


sub show_localtime {
  my $t = shift;
  scalar localtime $t;
}

sub show_localtime_list {
  my $t = shift;
  my @a = localtime $t;
  "@a\n"
}
  • (There is also a little presentation :))

It handles lots of cases, and seem to understand both timestamps in seconds and mini-seconds, etc.

$ localtime < ~/.histfile
<snip>
: Sat Sep 17 05:55:17 2016:0;cat localtime

You can display the whole history with human-readable timestamps using this one-liner taken from an answer on the zsh mailing list:

perl -lne 'm#: (\d+):\d+;(.+)# && printf "%s :: %s\n",scalar localtime $1,$2' $HISTFILE

I would recommend piping the output to a pager (less for example) to make it more readable.

Tags:

Timestamp

Zsh