#!/usr/bin/env perl # # hist - tcsh history with readable timestamps # # $Id$ use strict; use warnings; use POSIX qw(strftime); use Getopt::Std; # preprocess the command line so as to make it egrep-like foreach my $i ( 0 .. $#ARGV ) { if ( $ARGV[$i] =~ /^(-[^-v]*)v(.*)/ ) { # we have found a -v option my $rest = $1 . $2; $rest =~ s/[ev]//g; $i < $#ARGV or die "-v must be followed by arguument(s)\n"; splice( @ARGV, $i, 2, $rest, '-v', '--' ); last; } elsif ( $ARGV[$i] =~ /^(-[^-e]*)e(.*)/ ) { # we have found a -e option my $rest = $1 . $2; $rest =~ s/e//g; $i < $#ARGV or die "-e must be followed by arguument(s)\n"; splice( @ARGV, $i, 1, $rest, '--' ); last; } } warn join( ' ', $0, @ARGV ), "\n"; my %opt; getopts( 'ehtuv', \%opt ); $opt{h} and &HELP_MESSAGE; sub HELP_MESSAGE() { print STDERR << "ZZ"; Usage: $0 [-u] [-t] [-e|--|-v] [regexp1 [regexp2 [...]]] to list the current tcsh command history in a better format than tcsh's built-in history command. Options: -e -- -v must be followed by at least one more word; whatever follows it is treated as arguments, not options; the -v negates the result, causing exactly the lines to be printed that would not be printed otherwise -t prefix the commands with their timestamps in human-readable form -u only print the first occurrence of every command line ZZ exit(0); } my $histfile = $ENV{HOME} . '/.history'; open( my $fh, '<', $histfile ) or die "cannot read history file $histfile\n"; my $timestamp; my $rx; if (@ARGV) { my $filter = join( '|', @ARGV ); $rx = qr/$filter/; } my %seen; while (<$fh>) { if (/^#\+(\d+)/) { # the timestamp preceding the command $timestamp = $1; } elsif ( $opt{u} && $seen{$_}++ ) { # this command is a duplicate; skip it } elsif ( defined($rx) && !/$rx/ ) { # this command dosn't match the filter argument(s); skip it } else { # the command print strftime( '%m/%d/%Y %H:%M:%S', localtime($timestamp) ), ' ' if $opt{t}; print; } }