[comp.unix.shell] Comparing modified times of files

scottp@bwdlh504.bnr.ca (Scott Pace) (03/08/91)

I would like to be able to compare two files' time stamps, to see which one
is the oldest (or newest). How can I do this with sh?
I know about ksh and perl, but I want to know how it can be done with plain
old Bourne Shell.
I am running on HP-UX, if that makes a difference.
--
Scott Pace, Bell Northern Research, Ottawa, Canada, (613) 765-2631
scottp@bnr.ca

rob@b15.ingr.com (Rob Lemley) (03/09/91)

In <SCOTTP.91Mar8093523@bwdlh504.bnr.ca> scottp@bwdlh504.bnr.ca (Scott Pace) writes:

>I would like to be able to compare two files' time stamps, to see which one
>is the oldest (or newest). How can I do this with sh?

This script will print the name of the newest file:

	#
	# newer file1 file2
	#
	# print the name of the newest file on standard output
	# if files are the same age, nothing printed.
	#
	find "$1" -name "$1" -newer "$2" -print
	find "$2" -name "$2" -newer "$1" -print

The -name options are used to help avoid problems if directories
are given.  There will be other problems if the files are directories.

You could use just one find command, but then you wouldn't know
for sure if the files had the same date.

Another possibility is using "make":

	echo "file1:	file2" | make -f -

make will print 

	`file1' is up to date.

If $1 is newer or same age as $2

--
Rob

barnett@grymoire.crd.ge.com (Bruce Barnett) (03/10/91)

oldest=`ls -rt file1 file2 | head -1`
newest=`ls -t file1 file2 | head -1`
--
Bruce G. Barnett	barnett@crd.ge.com	uunet!crdgw1!barnett

art@pilikia.pegasus.com (Art Neilson) (03/11/91)

In article <SCOTTP.91Mar8093523@bwdlh504.bnr.ca> scottp@bwdlh504.bnr.ca (Scott Pace) writes:
>I would like to be able to compare two files' time stamps, to see which one
>is the oldest (or newest). How can I do this with sh?
>I know about ksh and perl, but I want to know how it can be done with plain
>old Bourne Shell.
>I am running on HP-UX, if that makes a difference.
>--
>Scott Pace, Bell Northern Research, Ottawa, Canada, (613) 765-2631
>scottp@bnr.ca

How about:

:
echo `ls -t $* | head -1`
-- 
Arthur W. Neilson III		| INET: art@pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pilikia!art

art@pilikia.pegasus.com (Art Neilson) (03/11/91)

In article <1991Mar10.212854.3183@pilikia.pegasus.com> art@pilikia.pegasus.com (Art Neilson) writes:
>In article <SCOTTP.91Mar8093523@bwdlh504.bnr.ca> scottp@bwdlh504.bnr.ca (Scott Pace) writes:
>>I would like to be able to compare two files' time stamps, to see which one
>>is the oldest (or newest). How can I do this with sh?
>How about:
>
>:
>echo `ls -t $* | head -1`

After posting this I realized the echo `` part was rather useless,
it should be:

:
ls -t $* | head -1
-- 
Arthur W. Neilson III		| INET: art@pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pilikia!art

itkin@mrspoc.Transact.COM (Steven M. List) (03/12/91)

scottp@bwdlh504.bnr.ca (Scott Pace) writes:

>I would like to be able to compare two files' time stamps, to see which one
>is the oldest (or newest). How can I do this with sh?
>I know about ksh and perl, but I want to know how it can be done with plain
>old Bourne Shell.
>I am running on HP-UX, if that makes a difference.

A simple way is to use find:

    find file1 -newer file2 -print

If file1 is newer than file2, then the name of "file1" will be printed
on stdout.  If not, then the output will be empty.  Unfortunately, in 
both cases the status value is 0, so you can't check for success or
failure.

If you're interested in something a bit faster that can also handle a
LIST of files, I wrote a little program a few years back that does
a few things:

    -   compares the last modification times of the files on the command
        line
    -   exits with the ordinal of the newest file as the status code
    -   prints the name of the newest file on standard output

So, just on the off-chance that someone can use it, here it is:
-----------CUT HERE-----------------------------------------------------------
#include    <sys/types.h>
#include    <sys/stat.h>
#include    <stdio.h>

struct stat sb, sbt;

int     max = 0;

char    *pgm;

main (ac, av)
int     ac;
char    *av[];
{
    register int i;

    register int error = 0;

    char    *strrchr ();

    sb.st_mtime = sbt.st_mtime = sb.st_ctime = sbt.st_ctime = 0;

    for (i = 1; i < ac; i++)
    {
        if (stat (av[i], &sbt) == 0)
        {
            if (sbt.st_mtime > sb.st_mtime || sbt.st_ctime > sb.st_ctime)
            {
                sb = sbt;
                max = i;
            }
        }
    }

    printf ("%s\n", av[max]);

    exit (max);
}
-----------CUT HERE-----------------------------------------------------------
No big deal, right?  But useful at times.
-- 
 +----------------------------------------------------------------------------+
 :                Steven List @ Transact Software, Inc. :^>~                  :
 :           Chairman, Unify User Group of Northern California                :
 :                         itkin@Transact.COM                                 :

merlyn@iwarp.intel.com (Randal L. Schwartz) (03/14/91)

In article <1991Mar11.183338.9082@mrspoc.Transact.COM>, itkin@mrspoc (Steven M. List) writes:
| If you're interested in something a bit faster that can also handle a
| LIST of files, I wrote a little program a few years back that does
| a few things:
| 
|     -   compares the last modification times of the files on the command
|         line
|     -   exits with the ordinal of the newest file as the status code
|     -   prints the name of the newest file on standard output
| 
| So, just on the off-chance that someone can use it, here it is:
| -----------CUT HERE-----------------------------------------------------------
[C code deleted]

For comparison, a similar routine in Perl:

perl -e '$n = shift; $m = -M $n; for (@ARGV) {$n = $_ if -M $_ < $m;} print $n'

Just another Perl hacker,
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel: putting the 'backward' in 'backward compatible'..."====/

mjf@mjm.mjm.com (Mark Fresolone) (03/16/91)

	ls -t file1 file2 | line	# returns newest
	ls -rt file1 file2 | line	# returns oldest

Mark Fresolone
Melillo Consulting/MJM Software
908-873-0075/Fax 908-873-2250
mjf@mjm.com, rutgers!mjm!mjf

tchrist@convex.COM (Tom Christiansen) (03/22/91)

From the keyboard of mjf@mjm.mjm.com (Mark Fresolone):
:
:	ls -t file1 file2 | line	# returns newest
:	ls -rt file1 file2 | line	# returns oldest

line: command not found

Perhaps you mean "sed -ne 1p"?

--tom

stuart@amc-gw.amc.com (Stuart Poulin) (03/23/91)

In article <930001@mjm.mjm.com> mjf@mjm.mjm.com (Mark Fresolone) writes:
>
>	ls -t file1 file2 | line	# returns newest
>	ls -rt file1 file2 | line	# returns oldest
>
>Mark Fresolone
>Melillo Consulting/MJM Software
>908-873-0075/Fax 908-873-2250
>mjf@mjm.com, rutgers!mjm!mjf


Or if you don't have "line":
    ls -t file1 file2 | (read XX; echo $XX)     # returns newest
    ls -rt file1 file2 |  (read XX; echo $XX)   # returns oldest

stuart@amc.com

]) (03/24/91)

In article <6350@amc-gw.amc.com> stuart@tfatf.amc.com (Stuart Poulin) writes:
>In article <930001@mjm.mjm.com> mjf@mjm.mjm.com (Mark Fresolone) writes:
>>	ls -t file1 file2 | line	# returns newest
>>	ls -rt file1 file2 | line	# returns oldest
>
>Or if you don't have "line":
>    ls -t file1 file2 | (read XX; echo $XX)     # returns newest
>    ls -rt file1 file2 |  (read XX; echo $XX)   # returns oldest

Okay, so this is sort of fun.  How 'bout:

# sh or ksh fragment
newest() {
	set -- ls -t $* 2>/dev/null
	echo $1
	}
oldest() {
	set -- ls -rt $* 2>/dev/null
	echo $1
	}

echo "The newest existing file in your list is `newest $*`"
echo "The oldest existing file in your list is `oldest $*`"
# end sh or ksh fragment

...Kris
-- 
Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS
Amdahl Corporation   |                |                    |
     [The opinions expressed above are mine, solely, and do not    ]
     [necessarily reflect the opinions or policies of Amdahl Corp. ]

yeates@motcid.UUCP (Tony J Yeates) (03/26/91)

krs@uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:

># sh or ksh fragment
>newest() {
>	set -- ls -t $* 2>/dev/null
>	echo $1
>	}
>oldest() {
>	set -- ls -rt $* 2>/dev/null
>	echo $1
>	}

Can you have functions in Bourne Shell scripts?  I thought this was 
only available in Ksh.

]) (03/26/91)

In article <6067@iron6.UUCP> yeates@motcid.UUCP (Tony J Yeates) writes:
>krs@uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:
>
>># sh or ksh fragment
>>newest() {
>>	set -- ls -t $* 2>/dev/null
>>	echo $1
>>	}
>>oldest() {
>>	set -- ls -rt $* 2>/dev/null
>>	echo $1
>>	}
>
>Can you have functions in Bourne Shell scripts?  I thought this was 
>only available in Ksh.

Well, it works in my Bourne shell.  :-)
...Kris
-- 
Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS
Amdahl Corporation   |                |                    |
     [The opinions expressed above are mine, solely, and do not    ]
     [necessarily reflect the opinions or policies of Amdahl Corp. ]

chip@tct.uucp (Chip Salzenberg) (03/28/91)

Compile and install this program.  End of problem.  Thanks, Henry.

/*
 * From Henry Spencer
 *
 * > 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?
 *
 * newer file1 file2
 *
 * exit with 0 status if file1 exists and file2 does not, or if file1's last
 * modified time is at least as recent as file2's.
 */

#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);
}
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
   "All this is conjecture of course, since I *only* post in the nude.
    Nothing comes between me and my t.b.  Nothing."   -- Bill Coderre

jensen@diku.dk (J|rgen Jensen) (04/01/91)

krs@uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:

  >In article <6067@iron6.UUCP> yeates@motcid.UUCP (Tony J Yeates) writes:
  >>krs@uts.amdahl.com (Kris Stephens [Hail Eris!]) writes:
  >>
  >>># sh or ksh fragment
  >>>newest() {
  >>>	set -- ls -t $* 2>/dev/null
  >>>	echo $1
  >>>	}
  >>>oldest() {
  >>>	set -- ls -rt $* 2>/dev/null
  >>>	echo $1
  >>>	}
  >>
  >>Can you have functions in Bourne Shell scripts?  I thought this was 
  >>only available in Ksh.
  >
  >Well, it works in my Bourne shell.  :-)
  >...Kris
  >-- 

well, *functions* work in my Bourne shell too, but the above 
doesn't -- shouldn't a pair of back-ticks (`) enter into the
thing somewhere?-)

my favorite way of comparing the recentness of *two* files follows
(I believe that was the original poster's problem):

   :
   #!/bin/sh -
   # 
   if find $1 -newer $2 -print -o -prune | read a
   then echo $1 is newer than $2
   fi

   # if your find doesn't have a "-prune"-predicate this
   # won't work for directories.  some older finds (SysV?)
   # didn't support filenames where "$1" is inserted
   # -- i think -- then this won't work at all, of course.


-- 

 . . . . . . . . . . . . . . . . . . . . . . . . . . j e n s e n
(jensen@diku.dk)
                        Opinions? -- These are rock-solid facts!