aab@silma.com (Andy Burgess) (07/24/90)
I need to compare the modification times of two files in a bourne shell script. I would like to do this without writing C code. Machine is Sparcstation 1 running SunOS 4.03c Thus I need a function: newer file1 file2 that returns 0 if file1 is newer than file2 else returns 1 Can it be done? Andy Burgess uunet!silma!aab 408 725 8908
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (07/25/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes:
:
: I need to compare the modification times of two files in a bourne shell
: script. I would like to do this without writing C code.
: Machine is Sparcstation 1 running SunOS 4.03c
:
: Thus I need a function:
:
: newer file1 file2
:
: that returns 0 if file1 is newer than file2 else returns 1
:
: Can it be done?
Several ways.
[ X`find file2 -newer file1 -print` = X ]
perl -e 'exit ((stat("file1"))[9] < (stat("file2"))[9])'
ls -lt file1 file2 | tail -1 | grep file2 >/dev/null
All of these should work on a Sun. Some machines may not have a -newer
option to find or a grep that returns a reasonable status. Some really
primitive machines don't have Perl. :-)
Larry Wall
lwall@jpl-devvax.jpl.nasa.gov
bjornmu@idt.unit.no (Bj|rn Munch) (07/25/90)
In article <1990Jul23.233044.2729@silma.com>, aab@silma.com (Andy Burgess) writes: |> |> I need to compare the modification times of two files in a bourne shell |> script. I would like to do this without writing C code. |> Machine is Sparcstation 1 running SunOS 4.03c |> |> Thus I need a function: |> |> newer file1 file2 |> |> that returns 0 if file1 is newer than file2 else returns 1 |> I needed the same thing once, and did it this way: test `ls -lt file1 file2 | head -1 | grep file1` This will not work if the name file1 is a substring of file2... It really ought to be simpler; after all, ls *has* the information you want, the rest is just needed to translate it. ___________________________________________________________________________ Bj|rn Munch | Div. of Comp. Science & Telematics, bjornmu@idt.unit.no | Norwegian Institute of Technology (NTH), "The Man With a Pipe in His Name" | Trondheim, Norway
leo@ehviea.ine.philips.nl (Leo de Wit) (07/25/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: | |I need to compare the modification times of two files in a bourne shell |script. I would like to do this without writing C code. |Machine is Sparcstation 1 running SunOS 4.03c | |Thus I need a function: | |newer file1 file2 | |that returns 0 if file1 is newer than file2 else returns 1 | |Can it be done? This is simple if you let make decide: case `echo "file1 : file2; :"| make -f -` in :) echo file1 is older than file2;; *) echo file1 is newer than file2;; esac (this does not exactly return 0 or 1, but you get the intent). On the other hand, many scripts I encounter that have to decide whether file1 is newer than file2 are of type makefile; you might want to check whether your problem fits this category. Leo.
celvin@EE.Surrey.Ac.UK (Chris Elvin) (07/25/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: > >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. >Machine is Sparcstation 1 running SunOS 4.03c > >Thus I need a function: > >newer file1 file2 > >that returns 0 if file1 is newer than file2 else returns 1 > How's about foobar=`find file2 -newer file1 -print | wc -l` Shell variable foobar will be 1 if file2 is newer than file1 or to answer the question as stated foobar=`find file1 !-newer file2 -print | wc -l` Hope this helps C. -- Chris Elvin C.Elvin@EE.Surrey.Ac.UK "Beware of low flying butterflies!" Dept of Elec. Eng, University of Surrey, Guildford, Surrey, GU2 5XH. England. PHONE: +44 483 509104 FAX: +44 483 34139
mab@ulysses.att.com (Muhammad Basit) (07/25/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: > >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. >Machine is Sparcstation 1 running SunOS 4.03c >Thus I need a function: >newer file1 file2 >that returns 0 if file1 is newer than file2 else returns 1 Another way you might find useful is to use find. e.g.: find mbox -newer .profile -exec date \; will execute the command date if 'mbox' is newer than '.profile' I think you can use it for your work with little effort. >Andy Burgess Muhammad Basit --------------- Muhammad Basit A person's mind is like a parachute: Email: mab@ulysses.ATT.COM To work it first has to be open. Basit@Mars.NJIT.EDU - I. Dont Remember
chet@cwns1.CWRU.EDU (Chet Ramey) (07/26/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: >newer file1 file2 >that returns 0 if file1 is newer than file2 else returns 1 Here's something I picked up a while back... /* * 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); } -- Chet Ramey ``See Figure 1.'' Network Services Group Case Western Reserve University chet@ins.CWRU.Edu
mike@x.co.uk (Mike Moore) (07/26/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: > >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. >Machine is Sparcstation 1 running SunOS 4.03c > >Thus I need a function: > >newer file1 file2 > >that returns 0 if file1 is newer than file2 else returns 1 > >Can it be done? Here is a way: newer() { file=$1 set `ls -t $1 $2` # func args are now changed [ $file = $1 ] && return 0 || return 1 } For those that don't know, the second line is an alternative form of: if [ $file = $1 ] then return 0 else return 1 fi Of course, file1 and file2 have to exist, and have to be files. If you don't want to use set, then: [ `ls -tC $1 $2 | sed 's/ .*$//'` = $1 ] && return 0 || return 1 And to do the whole thing properly: newer() { file=$1 [ ! -f $1 -o ! -f $2 ] && return 2 # error exit set `ls -dt $1 $2` # func args are changed [ $file = $1 ] && return 0 || return 1 } Now file1 and file2 don't have to exist and don't have to be files. Line #2 in this final version could be changed to two seperate lines: [ ! -f $1 ] && return 1 # since file2 is newer [ ! -f $2 ] && return 0 # since file1 is newer if you want a different effect. Using this method, then, on most machines, the only program actually read from disk and executed is ls (some may actually execute the '['). Happy Bourne Shell! Mike -- -------------------------------------------------------------------------- Usual disclaimer..... etc | mike@x.co.uk True Intelligence is not knowing all the answers, | it's knowing the right questions. |
andre@targon.UUCP (andre) (07/26/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. >Machine is Sparcstation 1 running SunOS 4.03c >Thus I need a function: >newer file1 file2 what about if [ -n "`find file2 -newer file1 -print`" ] then echo file2 is newer else echo file2 is not newer fi -- The mail| AAA DDDD It's not the kill, but the thrill of the chase. demon...| AA AAvv vvDD DD Ketchup is a vegetable. hits!.@&| AAAAAAAvv vvDD DD {nixbur|nixtor}!adalen.via --more--| AAA AAAvvvDDDDDD Andre van Dalen, uunet!hp4nl!targon!andre
lanzo@wgate.UUCP (Mark Lanzo) (07/26/90)
Someone asks: > > I need to compare the modification times of two files in a bourne shell > script. I would like to do this without writing C code. > Machine is Sparcstation 1 running SunOS 4.03c > Thus I need a function: > > newer file1 file2 > > that returns 0 if file1 is newer than file2 else returns 1 > Try this: #!/bin/sh newer() { f1="$1" set -- `ls -ct -- "$f1" "$2"` test "$1" = "$f1" return $? # This line isn't really necessary } as written, this function presupposes that $1 and $2 refer to accessible files (else the ls command will pop up with a "not found" type of error). -- Mark Lanzo Wandel & Goltermann Technologies, Inc. Home (919)481-2406 1030 Swabia Court Play (919)941-5730 Research Triangle Park uunet.uu.net!wgate.com!lanzo North Carolina 27709-3585
chris@vision.UUCP (Chris Davies) (07/26/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. If you insist... :-) The function returns 0 if file1 is newer than file2. Otherwise it returns 1. Note that there is no check to ensure both files exist. Syntax: newer file1 file2 newer() { F1=$1 F2=$2 echo "$F1\n$F2" > /tmp/newer$$ if ls -t "$F1" "$F2" | cmp -s - /tmp/newer$$ then RS=0 else RS=1 fi rm -f /tmp/newer$$ return $RS } Have fun... Chris -- VISIONWARE LTD | UK: chris@vision.uucp JANET: chris%vision.uucp@ukc 57 Cardigan Lane | US: chris@vware.mn.org OTHER: chris@vision.co.uk LEEDS LS4 2LE | BANGNET: ...{backbone}!ukc!vision!chris England | VOICE: +44 532 788858 FAX: +44 532 304676 -------------- "VisionWare: The home of DOS/UNIX/X integration" --------------
maart@cs.vu.nl (Maarten Litmaath) (07/27/90)
In article <Jul90.102745.21330@x.co.uk>, mike@x.co.uk (Mike Moore) writes: )... ) newer() { ) file=$1 ) set `ls -t $1 $2` # func args are now changed ) [ $file = $1 ] && return 0 || return 1 ) } Equivalently: newer() { file=$1 set `ls -t $1 $2` # func args are now changed [ $file = $1 ] } Sic! -- "and with a sudden plop it lands on usenet. what is it? omigosh, it must[...] be a new user! quick kill it before it multiplies!" (Loren J. Miller)
chet@cwns1.CWRU.EDU (Chet Ramey) (07/27/90)
>newer file1 file2 > >that returns 0 if file1 is newer than file2 else returns 1 If you didn't like the C program, then try this: newer() { if [ ! -f $1 ] ; then return 1 fi if [ ! -f $2 ] ; then return 0 fi if [ $1 -nt $2 ] ; then return 0 else return 1 fi } The `-nt' option to test exists in bash and ksh, at least. Chet -- Chet Ramey ``See Figure 1.'' Network Services Group Case Western Reserve University chet@ins.CWRU.Edu
jeff@onion.pdx.com (Jeff Beadles) (07/28/90)
In <8855@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes: :In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: :> :> I need to compare the modification times of two files in a bourne shell :> script. I would like to do this without writing C code. :> Machine is Sparcstation 1 running SunOS 4.03c :> :> Thus I need a function: :> :> newer file1 file2 :> :> that returns 0 if file1 is newer than file2 else returns 1 :> :> Can it be done? : :Several ways. ... :ls -lt file1 file2 | tail -1 | grep file2 >/dev/null This will only work some of the time. What if file1 is "foobar" and file2 is "bar" If you *had* to use this, I would recomend: ls -lt file1 file2 | tail -1 | grep "^file2$" >/dev/null UTek, the OS that I'm using now (UTek, a 4.2based OS.) It has a couple of options to test: TEST(1) COMMAND REFERENCE TEST(1) NAME test - condition command SYNOPSIS test expr [ expr ] DESCRIPTION ... -C filename Time of the last status change to filename (see stat(2)) -M filename Time of the last modification to filename (see stat(2)) -A filename Time of the last access to filename (see stat(2)) ... Thus, you can use: if test -M file1 -le -M file2 ; then ... else ... fi -Jeff -- Jeff Beadles jeff@onion.pdx.com jeff@quark.wv.tek.com
mayne@VSSERV.SCRI.FSU.EDU (William (Bill) Mayne) (07/30/90)
>:> Thus I need a function: >:> >:> newer file1 file2 >:> Others have suggested the use of make to do this, or better yet just use make to do whatever it is that depends upon file seniority. I think this is the most efficient route in terms of using standard unix tools and saving time. But the problem is not as simple as it seems, at least not when using SunOS. (I don't know what other versions of unix share this problem.) What if one of the files being compared is a symbolic link? What modification date and time should be compared? I have been surprised to learn the hard way that the date and time returned by ls and apparently used by make is when the link was created, regardless of the last modification to the actual file. Even if I later edit the file using the alias created by a link rather than the base name it is the base name, not the link, which gets a new modification date and time. I have some program constructions in which I have an awk program generate make files on the fly. Unless I build in enough intelligence for them to track down the base file for each reference I have quite a problem here. My first thought was to write a script which uses to touch to bring the timestamps of links up to date with their base files, but it turns out that touch also passes through to the base file, leaving the link alone. The use of inodes and links described in, for example, "The Unix Programming Environment" seemed so much more straight forward and convenient. As a relative newcomer to unix I am disappointed to find things rather different than what I had expected after reading some of the gurus. The reasons why I can't easily just have all my make files refer to base files rather than links are too complicated to go into here, but I am not just raising theoretical arguments or flames. (I will supply more details if anyone asks.) Others must have faced similar problems. I would be curious to know the reasons why the system behaves in such a surprising way (IMHO), but even more interested to know how others have worked with or around it in this area. Rereading this I see it is long. Just in case my main question gets hidden in the fog, I will restate it: The timestamp of a symbolic link is the time when the link was created, rather than the last modication of the file ultimately referenced. Thus a make file which refers to a symbolic link is fooled. How, short of tracing down all symbolic links when I generate a make file, can I work around this to use the actual modification times of all files or links? Other questions: If I really must trace down the links myself, is there an easy way to do it? Why was the system designed in a way that makes this use of make so difficult?
chris@mimsy.umd.edu (Chris Torek) (08/02/90)
In article <324@sun13.scri.fsu.edu> mayne@VSSERV.SCRI.FSU.EDU (William (Bill) Mayne) writes: >Others have suggested the use of make to [compare file modtimes].... >Just in case my main question gets hidden in the fog, I will restate >it: The timestamp of a symbolic link is the time when the link was >created, rather than the last modication of the file ultimately >referenced. Right. >Thus a make file which refers to a symbolic link is fooled. Wrong---or `should be wrong', at least. >Why was the system designed in a way that makes this use of make so >difficult? It was not. Although symbolic links do occupy an inode, and therefore have all the information a `stat' operation can find, they are not normally supposed to be examined by programs. Indeed, it requires a special system call (lstat()) to get this information: most system calls follow symlinks to their ultimate destinations. (The only other lookup operations that do not follow symlinks are chown(), probably because the space used for the target of the link is charged to the owner and thus this must be changeable, and readlink(), for the obvious reason. Removal operations, of course, do not follow symlinks. Normal creation operations do; opens for creating with O_EXCL do not.) Only a few programs---e.g., find (which must not follow symlinks since they may not form a tree) and ls (which should show the name and target, or whatnot)---have any business using lstat(). `Make' is not such a program. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
alex@impch.imp.com (Alex Hanselmann) (08/02/90)
In article <1990Jul23.233044.2729@silma.com> aab@silma.UUCP () writes: >I need to compare the modification times of two files in a bourne shell >script. I would like to do this without writing C code. >Machine is Sparcstation 1 running SunOS 4.03c > >Thus I need a function: > >newer file1 file2 > >that returns 0 if file1 is newer than file2 else returns 1 > >Can it be done? yes here's the script for newer. It's work with the modification time. -- #!/bin/sh #newer file1 file2 (mode) # returns 0 if file 1 is newer then file2 refered by mode (A/M/C (=> man ls) # returns 1 if file 2 is newer then file1 refered by mode ... # returns 2 on error if [ $# -lt 2 -o $# -gt 3 ] ;then echo "error in usage: incorrect argc" exit 2 fi NMODE='' if [ $# -eq 3 ] ; then case $3 in [Aa]) NMODE='u' ;; [Cc]) NMODE='c' ;; esac fi [ `ls -t$NMODE $1 $2 | line` = $1 ] && exit 0 exit 1 --- alex
andrew@alice.UUCP (Andrew Hume) (08/03/90)
if this is true, then sun's make is broken (as it often is). there is no reason why it should do an lstat rather than a stat to find out the modifcation time.