RFC: "-exit" option for find(1)

Peter Pentchev roam at ringlet.net
Fri Jul 16 08:24:23 PDT 2004


On Fri, Jul 16, 2004 at 05:28:57PM +0300, Peter Pentchev wrote:
> On Fri, Jul 16, 2004 at 11:58:07AM +0400, Denis Antrushin wrote:
> > Alfred Perlstein wrote:
> > >I'm up too late, this doesn't work because find returns
> > >success whenever it successfully runs thought everything.
> > >
> > >Perhaps the primary change to just "-exit" which would
> > >make find exit successfully, and if the primary is never
> > >encountered (ie. our find logic never hits it) find would
> > >exit with a non-zero exit status?
> > >
> > >Ideas?  Better ideas?
> > >
> > >The reason I want this is to avoid extracting a tarball
> > >over a directory that has files in it that are newer than
> > >the tarball.
> > >
> > >Neither tar nor find seem to make this easy...
> > What about this:
> > 
> > test -n "`find . -type f -newer ../src.tar.gz`" && echo hi
> 
> I believe Alfred's problem with this is that it will still traverse the
> whole hierarchy even after a match is found.  In some cases, the
> hierarchy may be huge, and if the match is within the first 100-200
> files, well... :)
> 
> I wonder if it wouldn't be a bit better to add to find(1) something like
> -maxmatches N, similar to Alfred's idea, but not limited to a single
> match?

Well, I've just gone ahead and implemented it: say hello to the new
-maxmatch N and -minmatch N primaries:

  -maxmatch n
     Always true; exits after printing out n matching filenames.  If
     any -maxmatch primary is specified, it applies to the entire
     expression even if it would not normally be evaluated.  -maxmatch
     0 makes find exit immediately without performing any filesystem
     traversal.

  -minmatch n
     Always true; exits with a non-zero exit code if less than n
     matching filenames were printed out at the end of the search.  If
     any -minmatch primary is specified, it applies to the entire
     expression even if it would not normally be evaluated.

Thus, -maxmatch 1 would help in Alfred's case.  Patch attached.

G'luck,
Peter

-- 
Peter Pentchev	roam at ringlet.net    roam at sbnd.net    roam at FreeBSD.org
PGP key:	http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint	FDBA FD79 C26F 3C51 C95E  DF9E ED18 B68D 1619 4553
I had to translate this sentence into English because I could not read the original Sanskrit.
-------------- next part --------------
Index: src/usr.bin/find/extern.h
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/extern.h,v
retrieving revision 1.21
diff -u -r1.21 extern.h
--- src/usr.bin/find/extern.h	28 May 2004 17:17:15 -0000	1.21
+++ src/usr.bin/find/extern.h	16 Jul 2004 15:09:49 -0000
@@ -68,6 +68,7 @@
 creat_f	c_links;
 creat_f	c_ls;
 creat_f	c_mXXdepth;
+creat_f	c_mXXmatch;
 creat_f	c_name;
 creat_f	c_newer;
 creat_f	c_nogroup;
@@ -116,6 +117,7 @@
 
 extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs;
 extern int mindepth, maxdepth;
+extern int minmatch, maxmatch, match;
 extern int regexp_flags;
 extern time_t now;
 extern int dotfd;
Index: src/usr.bin/find/find.1
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/find.1,v
retrieving revision 1.66
diff -u -r1.66 find.1
--- src/usr.bin/find/find.1	7 Jul 2004 19:57:15 -0000	1.66
+++ src/usr.bin/find/find.1	16 Jul 2004 15:19:36 -0000
@@ -442,6 +442,18 @@
 not normally be evaluated.
 .Ic -maxdepth Li 0
 limits the whole search to the command line arguments.
+.It Ic -maxmatch Ar n
+Always true; exits after printing out
+.Ar n
+matching filenames.
+If any
+.Ic -maxmatch
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
+.Ic Ic -maxmatch Li 0
+makes
+.Nm
+exit immediately without performing any filesystem traversal.
 .It Ic -mindepth Ar n
 Always true; do not apply any tests or actions at levels less than
 .Ar n .
@@ -451,6 +463,14 @@
 not normally be evaluated.
 .Ic -mindepth Li 1
 processes all but the command line arguments.
+.It Ic -minmatch Ar n
+Always true; exits with a non-zero exit code if less than
+.Ar n
+matching filenames were printed out at the end of the search.
+If any
+.Ic -minmatch
+primary is specified, it applies to the entire expression even if it would
+not normally be evaluated.
 .It Ic -mmin Ar n
 True if the difference between the file last modification time and the time
 .Nm
Index: src/usr.bin/find/find.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/find.c,v
retrieving revision 1.17
diff -u -r1.17 find.c
--- src/usr.bin/find/find.c	28 May 2004 17:17:15 -0000	1.17
+++ src/usr.bin/find/find.c	16 Jul 2004 15:16:10 -0000
@@ -181,6 +181,10 @@
 	PLAN *p;
 	int rval;
 
+	if (maxmatch == 0)
+		return (0);
+
+	match = 0;
 	tree = fts_open(paths, ftsoptions, (issort ? find_compare : NULL));
 	if (tree == NULL)
 		err(1, "ftsopen");
@@ -237,5 +241,11 @@
 			(p->execute)(p, NULL);
 	if (errno)
 		err(1, "fts_read");
+
+	if (match < minmatch) {
+		warnx("Only %d of requested %d matches found",
+		    match, minmatch);
+		rval = 1;
+	}
 	return (rval);
 }
Index: src/usr.bin/find/function.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/function.c,v
retrieving revision 1.50
diff -u -r1.50 function.c
--- src/usr.bin/find/function.c	28 May 2004 17:17:15 -0000	1.50
+++ src/usr.bin/find/function.c	16 Jul 2004 15:14:20 -0000
@@ -355,6 +355,36 @@
 }
 
 /*
+ * -maxmatch/-minmatch n functions --
+ *
+ *        If -maxmatch is specified, the search will stop after printing
+ *        out as many matching file names.  If -minmatch is specified and
+ *        at the end of the search there were less matching files found,
+ *        find will print out a warning and exit with a non-zero exit code.
+ *
+ *        Note that -maxmatch and -minmatch are handled specially in
+ *        find_execute() so their f_* functions are set to f_always_true().
+ */
+PLAN *
+c_mXXmatch(OPTION *option, char ***argvp)
+{
+	char *dstr;
+	PLAN *new;
+
+	dstr = nextarg(option, argvp);
+	if (dstr[0] == '-')
+		/* all other errors handled by find_parsenum() */
+		errx(1, "%s: %s: value must be positive", option->name, dstr);
+
+	new = palloc(option);
+	if (option->flags & F_MAXDEPTH)
+		maxmatch = find_parsenum(new, option->name, dstr, NULL);
+	else
+		minmatch = find_parsenum(new, option->name, dstr, NULL);
+	return new;
+}
+
+/*
  * -acl function --
  *
  *	Show files with EXTENDED ACL attributes.
@@ -1216,6 +1246,9 @@
 f_print(PLAN *plan __unused, FTSENT *entry)
 {
 	(void)puts(entry->fts_path);
+	match++;
+	if (match == maxmatch)
+		exit(0);
 	return 1;
 }
 
@@ -1238,6 +1271,9 @@
 {
 	fputs(entry->fts_path, stdout);
 	fputc('\0', stdout);
+	match++;
+	if (match == maxmatch)
+		exit(0);
 	return 1;
 }
 
Index: src/usr.bin/find/main.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/main.c,v
retrieving revision 1.15
diff -u -r1.15 main.c
--- src/usr.bin/find/main.c	14 Jun 2003 13:00:21 -0000	1.15
+++ src/usr.bin/find/main.c	16 Jul 2004 15:07:00 -0000
@@ -74,6 +74,8 @@
 int issort;         		/* do hierarchies in lexicographical order */
 int isxargs;			/* don't permit xargs delimiting chars */
 int mindepth = -1, maxdepth = -1; /* minimum and maximum depth */
+int minmatch = -1, maxmatch = -1; /* minimum and maximum number of matches */
+int match;			/* current number of matches */
 int regexp_flags = REG_BASIC;	/* use the "basic" regexp by default*/
 
 static void usage(void);
Index: src/usr.bin/find/option.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/option.c,v
retrieving revision 1.22
diff -u -r1.22 option.c
--- src/usr.bin/find/option.c	28 May 2004 17:17:15 -0000	1.22
+++ src/usr.bin/find/option.c	16 Jul 2004 15:01:11 -0000
@@ -94,7 +94,9 @@
 	{ "-links",	c_links,	f_links,	0 },
 	{ "-ls",	c_ls,		f_ls,		0 },
 	{ "-maxdepth",	c_mXXdepth,	f_always_true,	F_MAXDEPTH },
+	{ "-maxmatch",	c_mXXmatch,	f_always_true,	F_MAXDEPTH },
 	{ "-mindepth",	c_mXXdepth,	f_always_true,	0 },
+	{ "-minmatch",	c_mXXmatch,	f_always_true,	0 },
 	{ "-mmin",	c_Xmin,		f_Xmin,		0 },
 	{ "-mnewer",	c_newer,	f_newer,	0 },
 	{ "-mtime",	c_Xtime,	f_Xtime,	0 },
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20040716/ea49d731/attachment.bin


More information about the freebsd-hackers mailing list