[mod.std.unix] file times and shell commands

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (10/31/86)

From: mayer@rochester.arpa  (Jim Mayer)
Date: Wed, 29 Oct 86 22:15:54 est

I have two suggestions that fall into the "new feature" category.  The
first concerns file time manipulation from the shell.  The second
follows from the first, and concerns the combining power of the Bourne shell.

There doesn't appear to be any decent way to compare the last modified
times of files from the shell.  I have written programs to do this,
but that makes any scripts I write using the programs essentially
unexportable.

There are several approaches to fixing the problem:

1. Extend the "test" command, perhaps by borrowing the "-newer" syntax
   of "find".
2. Add a new command.  One possibility is
	"isconsistent file other-files..."
   which would return true if the first file was created after all of
   the "other-files".
3. Resign oneself to writing:
	if [ `ls -t a b | head -1` = a ]
	then echo "a was done later than b"
	fi

All three work, however the second points out a problem with the
Bourne shell: there is no "not" operator!

If an "isconsistent" command was implemented, then to write code that
(for example) recompiled a C file if the object file was out of date,
one would have to write:

	if isconsistent fu.o fu.c
	then true
	else cc -c fu.c
	fi

instead of

	if ! isconsistent fu.o fu.c
	then cc -c fu.c
	fi

Of course, one could always add an "isinconsistent" command, but that
avoids the point.  A "not" command that ran the command specified by
its arguments and inverted the exit code would be better, but would
still not handle things like "if ! (test1 || test2)" easily (I suspose
we could all write in conjunctive normal form (ugh!)).  If there was a
"not" operator then the Bourne shell syntax would be powerful enough
to express arbitrary boolean forms.

That, of course, raises the possibility of getting rid of the "test"
command entierly and replacing it with lots of little "gt" and "eq"
commands.  But that's another story.... (and hardly a job for a
standards group!)

-- Jim Mayer					Computer Science Department
(arpa) mayer@Rochester.EDU			University of Rochester
(uucp) rochester!mayer				Rochester, New York 14627


Volume-Number: Volume 8, Number 11

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/02/86)

From: pyramid!utzoo!henry (Henry Spencer)
Date: Fri, 31 Oct 86 21:25:31 CST

> There doesn't appear to be any decent way to compare the last modified
> times of files from the shell...

Before everybody starts inventing their own names for this, it should be
noted that V8 already has a program for this, newer(1).  It takes two
filenames as arguments, and exits with status 0 if and only if either
(a) the first exists and the second does not, or (b) both exist and the
first's modification time is at least as recent as the second's.  Other-
wise it exits with non-zero status.  (The preceding two sentences are
essentially the whole of the manual page for it.)

Relatively few people have V8, but in the absence of any other precedent
for what this facility should like look, it seems reasonable to follow
V8's lead.

Here is an independent rewrite, done from the manual page and not the
code, by me, hereby placed in the public domain:

/*
 * newer - is first file newer than second?
 */

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

main(argc, argv)
int argc;
char *argv[];
{
	struct stat file1;
	struct stat file2;

	if (argc != 3) {
		fprintf(stderr, "Usage: %s file1 file2\n", argv[0]);
		exit(2);
	}

	if (stat(argv[1], &file1) < 0)
		exit(1);
	if (stat(argv[2], &file2) < 0)
		exit(0);
	if (file1.st_mtime >= file2.st_mtime)
		exit(0);
	exit(1);
}

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

Volume-Number: Volume 8, Number 16

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/04/86)

From: arnold@emory.arpa  (Arnold D. Robbins)
Date: Mon, 3 Nov 86 13:20:48 EST
Organization: Math & Computer Science, Emory University, Atlanta

In article <6177@ut-sally.UUCP>:
>From: mayer@rochester.arpa  (Jim Mayer)
>Date: Wed, 29 Oct 86 22:15:54 est
>
>[....]
>
>There doesn't appear to be any decent way to compare the last modified
>times of files from the shell.  I have written programs to do this,
>but that makes any scripts I write using the programs essentially
>unexportable.
>
>There are several approaches to fixing the problem:
>
>1. Extend the "test" command, perhaps by borrowing the "-newer" syntax
>   of "find".
>[....]

The Korn shell did just this. In addition to the standard options listed
in the (System V) test(1) man page, there are four more options:

	-L	[ -L file ]; true if file is a symbolic link
	-nt	[ file1 -nt file2 ]; true if file1 is newer than file 2
	-ot	[ file1 -ot file2 ]; true if file1 is older than file 2
	-ef	[ file1 -ef file2 ]; true if file1 and file 2 same device/inode

The -L option will always be false on System V. The -ef goes through symbolic
links; you have to use [ f1 -ef f2 -a ! -L f1 -a ! -L f2 ] to be absolutely
sure.

>[....]
>All three work, however the second points out a problem with the
>Bourne shell: there is no "not" operator!

As has been pointed out in other forums, the S5 /bin/sh and the ksh both
support shell functions:

	not () {		# also "function not {" in ksh
		if "$@"
		then return 1
		else return 0
		fi
	}

	if not x y z a ...
	then
		whatever
	fi

Older /bin/sh versions leave you no choice:

	if x y z a ...
	then	:
	else
		whatever
	fi

A standard "not" operator would be nice, but shell functions and the test
stuff outlined above would be even better! (No, let's not start a debate
about shell functions vs. aliases vs. other shell features. We've already
been through that once on unix-wizards a while back.)
-- 
Arnold Robbins
CSNET:	arnold@emory	BITNET:	arnold@emoryu1
ARPA:	arnold%emory.csnet@csnet-relay.arpa
UUCP:	{ akgua, decvax, gatech, sb1, sb6, sunatl }!emory!arnold

Volume-Number: Volume 8, Number 33

std-unix@ut-sally.UUCP (Guest Moderator, John B. Chambers) (11/17/86)

>From gatech!gitpyr!nomad@seismo.UUCP Mon Nov 10 10:46:07 1986
Date: Mon, 10 Nov 86 09:29:38 est
From: Jay Joiner <gatech!gitpyr!nomad@seismo.UUCP>
News-Path: gatech!ut-sally!std-unix

About the file times question, how about using ls -t to put the files in
time order, then scanning the list with awk to find out whether the
files in question are in the right order or not.

Jay Joiner


Volume-Number: Volume 8, Number 53

std-unix@ut-sally.UUCP (12/04/86)

From: glc@akgua.UUCP (glc)
Date: 30 Nov 86 16:02:09 GMT
Organization: AT&T Technologies/Bell Labs, Atlanta

> > There doesn't appear to be any decent way to compare the last modified
> > times of files from the shell...
> 
> Before everybody starts inventing their own names for this, it should be
> noted that V8 already has a program for this, newer(1).  
 
The newer(1) program is a very good solution to the problem.  For
those who (for whatever reason) do not wish to implement it, there
is an alternate method using the "make" command.

Make(1) has the "-q" option which causes it to return zero or
non-zero after checking the dependencies.  Here is an example:

  if echo "$DEPENDENT:$CONTROL;:" | make -f - -q
    then # The dependent file is up-to-date
    else # The control file is newer that the dependent file
  fi

Cheers,
  Lindsay

Lindsay Cleveland  (akgua!glc) (404) 447-3909   Cornet 583-3909
AT&T Technologies/Bell Laboratories ... Atlanta, Ga



Volume-Number: Volume 8, Number 61