[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

newer



Thanks for your newer program.  I could not resist "improving" on it,
it seems to be an obsession I have... :-)

I sometimes want to compare a whole buch of files against a single
file.  For example, I can now write 

  newer -n `{newer -p mark} *.c

to get a list of all files that are newer than mark.  I can also say

  newer -o `{date+ -1 day %Z} *.c

to find out which ones are at least 1 day old, and so forth.  Yes, I
know I am duplicating some of the functionality of find...

Code appended.  Feel free to stuff it in your personal bit bucket!

- Harald

/* newer.c -- which file is newer? */

/*
   usage: newer [-s] [-l] [-acm] file1 file2\

   -s	Silent; exit codes only.  If -s is given, an existent file
	is considered newer than a non-existent one.
   -l	Use lstat, not stat to check times.  In other words, use this
	to check times of a symbolic link rather than the file it points to.
   -acm	Use the access, changed or modified (default) times.
	(Changed means writing the file or changing inode information).

   Alternative usages and modes:
   usage: newer [-l] [-acm] -p file ...
   -p   For each file named, print the corresponding time on stdout.
	This time is printed "raw" as a long integer.
   usage: newer [-s] [-l] [-acm] -[on] time file ...
	Here time is a long integer.
   -o   For each file, print the file name if it is at least as old as
	the named time.  If the -s option is used, return success if
	they are all that old, failure otherwise.
   -n	For each file, print the file name if it is newer than
	the named time.  If the -s option is used, return success if
	they are all newer, failure otherwise.

	Note: <sys/stdtypes> says
	typedef long time_t;
	If they had made it unsigned the format would last twice as long :-)

*/
#ifndef EXTENDED
#define EXTENDED 1
#endif
#if EXTENDED
# define OPTS "slacmpo:n:?"
#else
# define OPTS "slacm?"
#endif

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

#define streq(s, t)	(strcmp((s), (t)) == 0)

enum { ACCESSED, MODIFIED, CHANGED } which = MODIFIED;

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

#define	EXIT_TRUE	0
#define	EXIT_FALSE	1

extern int stat(), lstat();
int (*statfunc)() = stat;

void usage()
{
	fprintf(stderr, "usage: newer [-s] [-l] [-acm] file1 file2\n");
#if EXTENDED
	fprintf(stderr, "       newer      [-l] [-acm] -p file ...\n");
	fprintf(stderr, "       newer [-s] [-l] [-acm] -[on] time file ...\n");
#endif
	exit(2);
}

time_t gettime(s)
	char *s;
{
	struct stat st;
	if (statfunc(s, &st) == -1)
		return 0;
	switch (which) {
	case ACCESSED:	return st.st_atime;
	case MODIFIED:	return st.st_mtime;
	case CHANGED:	return st.st_ctime;
	}
}

int main(argc, argv)
	int argc;
	char *argv[];
{
	int c;
	time_t t1, t2;
	int silent = FALSE;
	extern int optind;
#if EXTENDED
	extern char *optarg;
	int print = FALSE;
	int newer = FALSE;
	int older = FALSE;
	time_t t0;
#endif

	while ((c = getopt(argc, argv, OPTS)) != EOF)
		switch (c) {
		case 's':	silent = TRUE;		break;
		case 'l':	statfunc = lstat;	break;
		case 'a':	which = ACCESSED;	break;
		case 'm':	which = MODIFIED;	break;
		case 'c':	which = CHANGED;	break;
#if EXTENDED
		case 'p':	print = TRUE;		break;
		case 'n':	newer = TRUE;
				t0 = atol(optarg);	break;
		case 'o':	older = TRUE;
				t0 = atol(optarg);	break;
#endif
		case '?':	usage();
		}
#if EXTENDED
      c=0; if (print) c++; if (newer) c++; if (older) c++;
      if (c>1) usage();
      if (c==0) {
#endif
	if (optind + 2 != argc)
		usage();

	t1 = gettime(argv[optind]);
	t2 = gettime(argv[optind + 1]);

	if (silent) {
		if (t1 != 0 || t2 != 0)
			exit(t1 >= t2 ? EXIT_TRUE : EXIT_FALSE);
		fprintf(stderr, "newer: %s and %s don't exist\n",
			argv[optind], argv[optind + 1]);
		exit(2);
	}

	if (t2 == 0) {
		perror(argv[optind + 1]);
		exit(2);
	}
	if (t1 == 0) {
		perror(argv[optind]);
		exit(2);
	}

	if (t1 >= t2)
		printf("%s\n", argv[optind]);
	else
		printf("%s\n", argv[optind + 1]);
#if EXTENDED
      } else if (print && silent) usage();
	else if (print)
	  for (c=optind; c<argc; c++)
	    printf("%ld\n", (long) gettime(argv[c]));
	else {
	  /* We must have newer or older set */
	  for (c=optind; c<argc; c++) {
	    if (gettime(argv[c])>t0) {
	      /* Is newer */
	      if (silent) {
		if (older) exit(1);
	      } else {
		if (newer) printf("%s\n", argv[c]); }
	    } else {
	      /* Is at least as old (or nonexistent) */
	      if (silent) {
		if (newer) exit(1);
	      } else {
		if (older) printf("%s\n", argv[c]); }}}}
#endif
	return 0;
}