[alt.sources] TIMESTAMP: a useful file filter by last modified time

taylor@limbo.Intuitive.Com (Dave Taylor) (07/01/90)

Timestamp is a handy utility I recently whipped up for some local
administrative needs that lists the subset of files given on the command 
line that are older (or newer) than the specified timestamp delta.

Timestamp can be included in shell scripts where the resolution of the 
'last modified' check of the "find" utility doesn't offer sufficiently 
high resolution.  Specifically, "timestamp" can be used to check for 
files that are older than "any" time, from seconds to days.  Further, 
with the use of the optional '-r' flag (to reverse the meaning of the 
command) "timestamp" can be used to find files newer than the specified 
time too.  (indeed, in conjunction, you could find all files that were
created during an specific 'slice' of time, even weeks ago).

	Enjoy!

						-- Dave Taylor
Intuitive Systems
Mountain View, California

taylor@limbo.intuitive.com    or   {uunet!}{decwrl,apple}!limbo!taylor

-- Shell archive:

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Dave Taylor <taylor@intuitive.com> on Sat Jun 30 12:38:08 1990
#
# This archive contains:
#	timestamp.1	timestamp.c	
#
# Error checking via wc(1) will be performed.
# Error checking via sum(1) will be performed.

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

if sum -r </dev/null >/dev/null 2>&1
then
	sumopt='-r'
else
	sumopt=''
fi

echo x - timestamp.1
cat >timestamp.1 <<'@EOF'
.TH TIMESTAMP 1L "" "" 
.SH NAME
timestamp \- check file modification times
.SH SYNOPSIS
.B timestamp 
[
.I \-q
] [
.I delta
]
.I filelist
.sp
.B timestamp 
[
.I \-q
] [
.I \-r
] [
.I delta
]
.I filelist 
.SH DESCRIPTION
.I Timestamp
is a utility that lists the subset of files given on the command
line that are older (or newer) than the specified timestamp delta.
.PP
This simple application is designed to be included in shell scripts
where the resolution of the 'last modified' check of the 
.I find
utility doesn't offer sufficiently high resolution.  Specifically,
.I timestamp
can be used to check for files that are older than 
.I any
time, from seconds to days.  Further, with the use of the optional
.I \-r
flag (to reverse the meaning of the command) 
.I timestamp
can be used to find files 
.I newer
than the specified time.
.SH OPTIONS
The 
.I timestamp
program has the following set of options available:
.TP
.B "-d N"
Add the specified number of days to the timestamp delta.
.TP
.B "-h N"
Add the specified number of hours to the timestamp delta.
.TP
.B "-m N"
Add the specified number of minutes to the timestamp delta.
.TP
.B "-s N"
Add the specified number of seconds to the timestamp delta.
.TP
.B "-q"
Quiet: don't complain about files that we can't open.
.TP
.B "-r"
Reverse the logic of the program; this will cause it to show
all files newer than the specified timestamp delta, rather
than older.
.SH EXAMPLES
Consider the case when you want to remove spurious lock files
from the 
.I sendmail
queue: we don't want to wait until they're a day or more old
to remove them (because that'd be a pretty slow delivery time
for email), so instead:
.nf
.in +0.5i

timestamp -q -m 30 /usr/spool/mqueue/l*

.in -0.5i
.fi
which would output the lock files that are at least 30 minutes
old in the spool directory.
.PP
By the same token, if we had our machine broken into, we could
find out which files in 
.I /tmp
had been modified in the past few minutes with:
.nf
.in +0.5i

timestamp -r -m 5 /tmp/*

.in -0.5i
.fi
as appropriate.
.SH SEE ALSO
find(1)
.SH AUTHOR
Dave Taylor, Intuitive Systems
.br
<taylor@limbo.Intuitive.Com>
.SH NOTES
This command checks the last modified time of the files, not
the created or last accessed times.  It's possible that we've
choosen the wrong option in this case.
.PP
The 
.I \-q
option might well be something that should be there as a
default value too...
@EOF
set `sum $sumopt <timestamp.1`; if test $1 -ne 15993
then
	echo ERROR: timestamp.1 checksum is $1 should be 15993
fi
set `wc -lwc <timestamp.1`
if test $1$2$3 != 1084372406
then
	echo ERROR: wc results of timestamp.1 are $* should be 108 437 2406
fi

chmod 644 timestamp.1

echo x - timestamp.c
cat >timestamp.c <<'@EOF'
/**				timestamp.c				**/

/** This program prints the names of all files in the argument list that
    are at least as old as the time specified (with no default)

	(C) Copyright 1990 Dave Taylor  <taylor@intuitive.com>
	(C) Copyright 1990 Intuitive Systems

    You may do whatever you want with this program so long as the 
    copyright notice above remains intact.
**/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>

#ifndef TRUE
# define TRUE			1
# define FALSE			0
#endif

#define SLEN			128

#define SECONDS_PER_MINUTE	60
#define SECONDS_PER_HOUR	3600		/* 	60 * 60 	*/
#define SECONDS_PER_DAY		86400		/*    60 * 60 * 24	*/

#define compare_times(ft,ct,test) 	(test ? ft <= ct : ft > ct)

int getopt();
char *ctime();

main(argc, argv)
char **argv;
{
	extern int optind;
	extern char *optarg;

	int c, older = TRUE, quiet = FALSE;
	long hours = 0L, minutes = 0L, seconds = 0L, days = 0L;
	long current_time, comparator;
	char  buffer[SLEN];
	struct stat statbuf;
	
	while ((c = getopt(argc, argv, "d:h:m:qrs:")) != EOF) {
	  switch (c) {
	     case 'd' : days = atoi(optarg);		break;
	     case 'h' : hours = atoi(optarg);		break;
	     case 'm' : minutes = atoi(optarg);		break;
	     case 'q' : quiet = TRUE;			break;
	     case 'r' : older = FALSE;			break;
	     case 's' : seconds = atoi(optarg);		break;
	      default : usage();
	  }
	}

	/** now compute our offset from the current time **/

	current_time = time(0);
	comparator = current_time - (days * SECONDS_PER_DAY)
				  - (hours * SECONDS_PER_HOUR)
				  - (minutes * SECONDS_PER_MINUTE)
				  - seconds;

	while (optind < argc) {

	  if ((stat(argv[optind], &statbuf) < 0) && (! quiet))  {
	    sprintf(buffer, "Failed trying to stat file '%s'", argv[optind]);
	    perror(buffer);
	  }

	  if (compare_times(statbuf.st_mtime, comparator, older))
	    printf("%s\n", argv[optind]);

	  optind++;
	}

	exit(0);
}

usage()
{
	fprintf(stderr, "Usage: timestamp [delta] [-q] [-r] filenames\n");
	fprintf(stderr, "\nWhere delta can be any combination of:\n");
	fprintf(stderr, "\t-d N  \tOlder than N days in the past\n");
	fprintf(stderr, "\t-h N  \tOlder than N hours in the past\n");
	fprintf(stderr, "\t-m N  \tOlder than N minutes in the past\n");
	fprintf(stderr, 
	    "\t-q    \tQuiet: don't complain about nonexistent files\n");
	fprintf(stderr, 
	    "\t-r    \tReverse logic: show newer, rather than older\n");
	fprintf(stderr, "\t-s N  \tOlder than N seconds in the past\n");
 
	exit(1);
}
@EOF
set `sum $sumopt <timestamp.c`; if test $1 -ne 39407
then
	echo ERROR: timestamp.c checksum is $1 should be 39407
fi
set `wc -lwc <timestamp.c`
if test $1$2$3 != 963562510
then
	echo ERROR: wc results of timestamp.c are $* should be 96 356 2510
fi

chmod 644 timestamp.c

exit 0