Subject: making find(1) return immediately when finding a file
To: None <tech-userlevel@netbsd.org>
From: Jan Schaumann <jschauma@netmeister.org>
List: tech-userlevel
Date: 02/16/2006 22:16:39
--kORqDWCi7qDJ0mEj
Content-Type: multipart/mixed; boundary="PNTmBPCT7hxwcZjr"
Content-Disposition: inline


--PNTmBPCT7hxwcZjr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,

I recently came across an instance, where I would have liked to be able
to use find(1) to simply check if a directory contains any file with a
modification time newer than a given other file, but I do not care what
the files name is, or if there are more than one.  That is, once I have
found one file, I want find(1) to exit, rather than continue to traverse
the entire filesystem rooted under the given directory.

I don't think that any of the existing options allows find(1) to exit
right away.  Attached is a small diff that adds the '-return' flag to
let find return immediately after a previous condition was met.

This makes it easier to script find(1), or even to use it in interactive
use.  What do you think, does this option make sense at all?

-Jan

--=20
http://www.ncadp.org

--PNTmBPCT7hxwcZjr
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Content-Transfer-Encoding: quoted-printable

Index: extern.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/extern.h,v
retrieving revision 1.22
diff -b -u -r1.22 extern.h
--- extern.h	9 Nov 2005 00:47:16 -0000	1.22
+++ extern.h	17 Feb 2006 03:04:00 -0000
@@ -82,6 +82,7 @@
 PLAN	*c_printx __P((char ***, int));
 PLAN	*c_prune __P((char ***, int));
 PLAN	*c_regex __P((char ***, int));
+PLAN	*c_return __P((char ***, int));
 PLAN	*c_size __P((char ***, int));
 PLAN	*c_type __P((char ***, int));
 PLAN	*c_user __P((char ***, int));
Index: find.1
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/find.1,v
retrieving revision 1.55
diff -b -u -r1.55 find.1
--- find.1	9 Nov 2005 00:47:16 -0000	1.55
+++ find.1	17 Feb 2006 03:04:00 -0000
@@ -492,6 +492,11 @@
 .Ar regexp .
 This is a match on the whole path, not a search for the regular expression
 within the path.
+.It Ic -return
+This primary always evaluates to true.
+It causes
+.Nm
+to stop traversing the filesystem immediately if a previous condition was =
met.
 .It Ic -size Ar n Ns Op Cm c
 True if the file's size, rounded up, in 512-byte blocks is
 .Ar n  .
Index: find.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/find.c,v
retrieving revision 1.20
diff -b -u -r1.20 find.c
--- find.c	12 Oct 2005 20:03:59 -0000	1.20
+++ find.c	17 Feb 2006 03:04:00 -0000
@@ -189,14 +189,16 @@
 	char **paths;		/* array of pathnames to traverse */
 {
 	PLAN *p;
-	int rval;
+	int rval, cval;
 	sigset_t s;
=20
+	cval =3D 1;
+
 	if (!(tree =3D fts_open(paths, ftsoptions, issort ? ftscompare : NULL)))
 		err(1, "ftsopen");
=20
 	sig_lock(&s);
-	for (rval =3D 0; (g_entry =3D fts_read(tree)) !=3D NULL; sig_lock(&s)) {
+	for (rval =3D 0; cval && (g_entry =3D fts_read(tree)) !=3D NULL; sig_lock=
(&s)) {
 		sig_unlock(&s);
 		switch (g_entry->fts_info) {
 		case FTS_D:
@@ -230,8 +232,10 @@
 		 * the work specified by the user on the command line.
 		 */
 		for (p =3D plan; p && (p->eval)(p, g_entry); p =3D p->next)
-			;
+			if (p->type =3D=3D N_RETURN)
+				cval =3D 0;
 	}
+
 	sig_unlock(&s);
 	if (errno)
 		err(1, "fts_read");
Index: find.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/find.h,v
retrieving revision 1.20
diff -b -u -r1.20 find.h
--- find.h	9 Nov 2005 00:47:16 -0000	1.20
+++ find.h	17 Feb 2006 03:04:01 -0000
@@ -45,7 +45,7 @@
 	N_INAME, N_INUM, N_IREGEX, N_LINKS, N_LS, N_MINDEPTH, N_MAXDEPTH,
 	N_MMIN, N_MTIME, N_NAME, N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK,
 	N_OPENPAREN, N_OR, N_PATH, N_PERM, N_PRINT, N_PRINT0, N_PRINTX,
-	N_PRUNE, N_REGEX, N_SIZE, N_TYPE, N_USER, N_XDEV
+	N_PRUNE, N_REGEX, N_RETURN, N_SIZE, N_TYPE, N_USER, N_XDEV
 };
=20
 /* node definition */
Index: function.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/function.c,v
retrieving revision 1.52
diff -b -u -r1.52 function.c
--- function.c	9 Nov 2005 00:47:16 -0000	1.52
+++ function.c	17 Feb 2006 03:04:02 -0000
@@ -1509,6 +1509,14 @@
 	return (c_regex_common(argvp, isok, N_IREGEX, REG_BASIC|REG_ICASE));
 }
=20
+PLAN *
+c_return(argvp, isok)
+	char ***argvp;
+	int isok;
+{
+	return (palloc(N_RETURN, f_always_true));
+}
+
 /*
  * -size n[c] functions --
  *
Index: option.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/usr.bin/find/option.c,v
retrieving revision 1.22
diff -b -u -r1.22 option.c
--- option.c	9 Nov 2005 00:47:16 -0000	1.22
+++ option.c	17 Feb 2006 03:04:02 -0000
@@ -101,6 +101,7 @@
 	{ "-printx",	N_PRINTX,	c_printx,	0 },
 	{ "-prune",	N_PRUNE,	c_prune,	0 },
 	{ "-regex",	N_REGEX,	c_regex,	1 },
+	{ "-return",	N_RETURN,	c_return,	0 },
 	{ "-size",	N_SIZE,		c_size,		1 },
 	{ "-type",	N_TYPE,		c_type,		1 },
 	{ "-user",	N_USER,		c_user,		1 },

--PNTmBPCT7hxwcZjr--

--kORqDWCi7qDJ0mEj
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (NetBSD)

iD8DBQFD9UAXfFtkr68iakwRAsNlAKDHb2Y2GdleT9xw8e4K3Z6Vjvv1GgCbBNZH
EjWC/q1VKJbY+ML5RX1yxWk=
=ez7h
-----END PGP SIGNATURE-----

--kORqDWCi7qDJ0mEj--