roy@phri.UUCP (Roy Smith) (04/24/87)
A user posed a problem which I can't solve. She wants to find all the files named *refs which are newer than a file called INDEX in the same directory. Thus she wants to know if any of ./x/foorefs, ./x/barrefs or ./x/bazrefs is newer than ./x/INDEX, and if ./y/z/refs is newer than ./y/z/INDEX, etc. I can't think of how to do this with find, or even any combination of find and any other standard tools. We're running MtXinu 4.3BSD/NFS on a Vax and Sun-3.1 on some Sun-3's. The obvious % find . "*refs" -newer INDEX -print finds *refs files which are newer than INDEX in the directory in which I ran the find. This is not, unfortunately, what I need. The Sun version of make has a -q option which I could use to do something like % find . -name INDEX -exec make -q INDEX ';' but this will only work on the Suns, and there is still the problem of how to phrase the Makefiles and where to put them. Of course, if the MtXinu NFS support worked better I would contemplate running this on a Sun CPU mounting the Vax disk, but it doesn't, so I won't. I could envision something horrible along the lines of % find . -type d -exec find '{}' -type d -prune -name '"*refs"' \ -newer INDEX -exec pwd -print '";"' ';' but I no longer do the type of drugs required to seriously contemplate doing that. I havn't wasted the time to get the exact syntax of the above correct so please don't bother flaming me about messing up the double layer of quotes or some other silly detail. It was meant as a general idea, not a finished product. Note that you need the "-exec pwd" in the inner-level find because all "-print" will say is "./foorefs" which isn't useful. Another hair-brained (a cross between hairy and brain-damaged?) idea centers around doing "ls -lt INDEX *refs" and checking to see that the first output line contains (or actually doesn't contain) INDEX, perhaps by piping it through "head -1 | grep INDEX". This gives (roughly) % find . -type d \ -exec sh -c 'ls -lt {}/INDEX {}/*refs | head -1 | egrep -vs INDEX' ';' \ -print which is also too sick to think about doing, let alone explaining to a non-wizard. Besides, I wouldn't count on the "sh -c" to properly pass back the exit status of the pipeline (earlier Berkeley versions of sh did this wrong; I have no idea if the 4.3 version is fixed or not), and you run into problems if the sh dies because the *refs expansion doesn't work in a particular directory. Is there really no easy way to do this? -- Roy Smith, {allegra,cmcl2,philabs}!phri!roy System Administrator, Public Health Research Institute 455 First Avenue, New York, NY 10016 "you can't spell deoxyribonucleic without unix!"
mkhaw@teknowledge-vaxc.ARPA (Michael Khaw) (04/24/87)
In article <2645@phri.UUCP> roy@phri.UUCP (Roy Smith) writes: > > A user posed a problem which I can't solve. She wants to find all >the files named *refs which are newer than a file called INDEX in the same >directory. Thus she wants to know if any of ./x/foorefs, ./x/barrefs or >./x/bazrefs is newer than ./x/INDEX, and if ./y/z/refs is newer than >./y/z/INDEX, etc. I can't think of how to do this with find, or even any How about (csh) % foreach dir (x y) # `pwd` == parent of x and y ? find $dir -name '*refs' -newer $dir/INDEX -print ? end Mike Khaw -- internet: mkhaw@teknowledge-vaxc.arpa usenet: {hplabs|sun|ucbvax|decwrl|sri-unix}!mkhaw%teknowledge-vaxc.arpa USnail: Teknowledge Inc, 1850 Embarcadero Rd, POB 10119, Palo Alto, CA 94303
trent@cit-vax.Caltech.Edu (Ray Trent) (04/24/87)
In article <2645@phri.UUCP> roy@phri.UUCP (Roy Smith) writes: > > A user posed a problem which I can't solve. She wants to find all >the files named *refs which are newer than a file called INDEX in the same >directory. Thus she wants to know if any of ./x/foorefs, ./x/barrefs or Here's a cute solution: Place the following into the Makefile for each of the directories: ---start of new lines--- INDEX : *refs echo "`pwd`: "; ls $? ---end of new lines--- and execute: find . -name INDEX -exec make -s INDEX \; I just tried this and it does exactly what you requested. The -name INDEX part of the find command is so that make doesn't get executed in directories not containing an INDEX. The -s option on make causes the output command not to be echoed. The $? in the output command in the Makefile refers to all prerequitsites that are not up to date. This way of doing it has the advantage that you can format the output pretty much any way you want to by changing the command line in the Makefile. Remember, you too can use make for *anything*. <snicker, snicker> -- <this space for rent> ../ray\.. (trent@csvax.caltech.edu, rat@caltech.bitnet, ...seismo!cit-vax!trent)
rmg@mips.UUCP (Richard M. Geiger) (04/25/87)
In article <2645@phri.UUCP> roy@phri.UUCP (Roy Smith) writes: > > A user posed a problem which I can't solve. She wants to find all >the files named *refs which are newer than a file called INDEX in the same >directory. Thus she wants to know if any of ./x/foorefs, ./x/barrefs or >./x/bazrefs is newer than ./x/INDEX, and if ./y/z/refs is newer than >./y/z/INDEX, etc. I can't think of how to do this with find, or even any >combination of find and any other standard tools. We're running MtXinu >4.3BSD/NFS on a Vax and Sun-3.1 on some Sun-3's. Seems like you should be able to skin this cat with something like this... a script, /user/rmg/bin/sinceindex: #!/bin/sh echo ===== "$1" ===== cd "$1" ls -t *refs INDEX 2>/dev/null | sed -n -e '/^INDEX$/ p' and a find command: find . -type d -exec /user/rmg/bin/sinceindex {} \; This seems to work. I fiddled for a bit with getting it all on one command line, (to keep from having to have the script), but ran out of patience. I expect it could be done without the script. -- - Rich Geiger {decvax,ucbvax,ihnp4}!decwrl!mips!rmg MIPS Computer Systems, 930 E. Arques, Sunnyvale, CA 94086 (408) 720-1700 x308 [Day Job] (408) 739-7911 [home]
chris@mimsy.UUCP (Chris Torek) (04/25/87)
In article <2645@phri.UUCP> roy@phri.UUCP (Roy Smith) writes: >[problem:] find all the files named *refs which are newer than a >file called INDEX in the same directory [as the *refs files]. If you have the `newer' program, this is easy: use -exec and a short script that runs newer on the given file and the equivalent INDEX file. Without newer, the most efficient way to tackle this is, probably, to first list all the `*refs' files with directories: find . -name \*refs -print | Break up the result by directory name: awk -F/ '{ dir = substr($0, 1, length($0) - length($NF)); if (dir != last) { if (any) print "/shazam"; any = 0; } else { if (any == 0) { any = 1; print "testthem " dir " << \\/shazam" } print $NF } }' | sh The `testthem' script then looks something like this: cd $1 if [ ! -f INDEX ]; then echo "$1: no INDEX file" cat # list them all exit 1 fi echo $1 find `cat` -newer INDEX -print and of course you can play games with formatting. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: seismo!mimsy!chris ARPA/CSNet: chris@mimsy.umd.edu
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/26/87)
In article <6454@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >If you have the `newer' program, ... /* newer -- test file modification dates last edit: 86/03/30 D A Gwyn */ #ifndef lint static char SCCS_ID[] = "@(#)newer.c 1.1"; #endif #include <sys/types.h> #include <sys/stat.h> #define EXIT _exit /* non-STDIO exit(), if available */ #define STDERR 2 /* standard error file descriptor */ extern void EXIT(); extern int stat(), write(); main( argc, argv ) int argc; char *argv[]; { static char usage[] = "Usage: newer file1 file2\n"; static struct stat file1; /* file1 statistics */ static struct stat file2; /* file2 statistics */ if ( argc != 3 ) { /* wrong number of arguments */ (void)write( STDERR, usage, sizeof usage - 1 ); EXIT( 3 ); } if ( stat( argv[1], &file1 ) != 0 ) EXIT( 2 ); /* file1 doesn't exist */ if ( stat( argv[2], &file2 ) != 0 ) EXIT( 0 ); /* file2 doesn't exist */ #ifdef lint return file1.st_mtime < file2.st_mtime ? 1 : 0; #else EXIT( file1.st_mtime < file2.st_mtime ? 1 : 0 ); #endif }
rbj@icst-cmr.arpa (Root Boy Jim) (04/27/87)
Without newer, the most efficient way to tackle this is, probably, to first list all the `*refs' files with directories: find . -name \*refs -print | torAWK-script Except that it might be worth solving the smaller problem first. First find only the directorys containing an INDEX, then figure out what *refs are out of date and what to do with them. Of course if you assume that in no INDEX exists that all the *refs are out of date, as make would, it makes no difference. (Root Boy) Jim "Just Say Yes" Cottrell <rbj@icst-cmr.arpa> I always have fun because I'm out of my mind!!!
davidsen@steinmetz.steinmetz.UUCP (William E. Davidsen Jr) (04/29/87)
In article <2645@phri.UUCP> roy@phri.UUCP (Roy Smith) writes: > > A user posed a problem which I can't solve. She wants to find all >the files named *refs which are newer than a file called INDEX in the same >directory. Thus she wants to know if any of ./x/foorefs, ./x/barrefs or >./x/bazrefs is newer than ./x/INDEX, and if ./y/z/refs is newer than >./y/z/INDEX, etc. I can't think of how to do this with find, or even any >combination of find and any other standard tools. We're running MtXinu >4.3BSD/NFS on a Vax and Sun-3.1 on some Sun-3's. After looking at some of the solutions to this, I decided that my first thought was no more confusing and used something we all have, the Bourne shell. $ find . -type d -print | > while read dirname > do > find $dirname -name '*refs' -newer $dirname/INDEX -print > done Note that if you don't escape the "*refs" as some of the suggested solutions have (not) done, and you have a matching file in the current directory, you will get filename expansion and the find will fail. -- bill davidsen sixhub \ ARPA: wedu@ge-crd.arpa ihnp4!seismo!rochester!steinmetz -> crdos1!davidsen chinet / "Stupidity, like virtue, is its own reward"
karl@haddock.UUCP (Karl Heuer) (04/29/87)
In article <5797@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn) writes: [source for program "newer", ending with] >#ifdef lint > return file1.st_mtime < file2.st_mtime ? 1 : 0; >#else > EXIT( file1.st_mtime < file2.st_mtime ? 1 : 0 ); >#endif I don't mean to flame the author's style, but what's wrong with EXIT( file1.st_mtime < file2.st_mtime ? 1 : 0 ); /* NOTREACHED */ ? That's what the lintpragma is for. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
jfh@killer.UUCP (John Haugh) (04/30/87)
That ought to do the trick. '*refs' was the name of the files you were looking for. Find(1) does the file name matching itself, so you want to pass the pattern, not the expansion to find(1). - John. "You can't spell Fred without Federalism" -- John "Fred" Haugh II.
tim@ism780c.UUCP (Tim Smith) (05/09/87)
If you are not going to do something a lot, it is sometimes faster to just write a shell script rather than try to figure out exactly which tools are right for the job. In this example, the following would work: $ find . -type d | dodir where dodir is the following shell script: #!/bin/sh BASE=`pwd` while read DIR do cd $BASE cd $DIR if [ -r INDEX ] then mkdir TEMP.$$ ln *xrefs TEMP.$$ ln INDEX TEMP.$$ cd TEMP.$$ if ls -lt | sed 2q | fgrep INDEX > /dev/null 2>&1 then # # Get here if INDEX is newer than # all the refs files # else # # Get here if some ref files are newer # than INDEX # fi cd .. rm -rf TEMP.$$ fi done Ok, I admit it is a kludge, but it works! -- Tim Smith "Froh wie seine Sonnen fliegen sdcrdcf!ism780c!tim Durch des Himmels praecht'gen Plan, Laufet, Brueder, eure Bahn, Freudig wie ein Held zum Siegen"