[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RFC: "-contains" option
From: |
Eddie Kohler |
Subject: |
RFC: "-contains" option |
Date: |
Sat, 21 Feb 2009 10:20:04 -0800 |
User-agent: |
Thunderbird 2.0.0.19 (X11/20090105) |
Hi,
I frequently use "find" to search collections of files while pruning certain
directories. However, I'd often like to prune build directories and the like,
and these don't have consistent names.
One solution is to prune directories that contain a file named ".find-ignore".
This can be coded up with, e.g, "-execdir test -e .find-ignore \; -prune".
Unfortunately, this makes find much slower -- on the relevant directory tree,
"find . -type d , -true" takes 1.44s, while "find . \( -type d -a -execdir
test -e .find-ignore \; \) , -true" takes 98.53s.
The patch below adds a "-contains NAME" test to find. The test is true if the
current filename is a directory, and that directory contains a file named
NAME. I wonder if it is worth including, or if anyone has comments. (The
patch doesn't yet update the texinfo.)
Thanks,
Eddie Kohler
diff -ru findutils-4.2.33/find/defs.h findutils-4.2.33-p/find/defs.h
--- findutils-4.2.33/find/defs.h 2007-12-08 06:00:45.000000000 -0800
+++ findutils-4.2.33-p/find/defs.h 2009-02-21 09:09:33.000000000 -0800
@@ -435,6 +435,7 @@
boolean pred_cmin PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
boolean pred_cnewer PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
boolean pred_comma PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
+boolean pred_contains PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
boolean pred_ctime PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
boolean pred_delete PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
boolean pred_empty PARAMS((char *pathname, struct stat *stat_buf, struct
predicate *pred_ptr));
diff -ru findutils-4.2.33/find/find.1 findutils-4.2.33-p/find/find.1
--- findutils-4.2.33/find/find.1 2007-04-15 12:04:34.000000000 -0700
+++ findutils-4.2.33-p/find/find.1 2009-02-21 09:32:26.000000000 -0800
@@ -260,6 +260,8 @@
\-L option is in effect, the status-change time of the file it points
to is always used.
+.IP "\-contains \fIname\fR"
+File is a directory and contains a file named \fIname\fR.
.IP "\-ctime \fIn\fR"
File's status was last changed \fIn\fR*24 hours ago.
See the comments for
diff -ru findutils-4.2.33/find/parser.c findutils-4.2.33-p/find/parser.c
--- findutils-4.2.33/find/parser.c 2007-12-08 06:00:47.000000000 -0800
+++ findutils-4.2.33-p/find/parser.c 2009-02-21 09:33:19.000000000 -0800
@@ -83,6 +83,7 @@
static boolean parse_cmin PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
static boolean parse_cnewer PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
static boolean parse_comma PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
+static boolean parse_contains PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
static boolean parse_ctime PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
static boolean parse_daystart PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
static boolean parse_delete PARAMS((const struct parser_table*, char
*argv[], int *arg_ptr));
@@ -157,6 +158,7 @@
static boolean insert_regex PARAMS((char *argv[], int *arg_ptr, const struct
parser_table *entry, int regex_options));
static boolean insert_fprintf PARAMS((FILE *fp, const struct parser_table
*entry, PRED_FUNC func, char *argv[], int *arg_ptr));
+static boolean check_name_arg PARAMS((const char *pred, const char *arg));
static struct segment **make_segment PARAMS((struct segment **segment, char
*format, int len, int kind));
static boolean insert_exec_ok PARAMS((const char *action, const struct
parser_table *entry, char *argv[], int *arg_ptr));
static boolean get_num_days PARAMS((char *str, uintmax_t *num_days, enum
comparison_type *comp_type));
@@ -213,6 +215,7 @@
PARSE_TEST ("atime", atime),
PARSE_TEST ("cmin", cmin), /* GNU */
PARSE_TEST ("cnewer", cnewer), /* GNU */
+ PARSE_TEST ("contains", contains),
PARSE_TEST ("ctime", ctime),
PARSE_POSOPT ("daystart", daystart), /* GNU */
PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD
*/
@@ -546,6 +549,24 @@
}
static boolean
+parse_contains (const struct parser_table* entry, char **argv, int *arg_ptr)
+{
+ struct predicate *our_pred;
+
+ if ((argv == NULL) || (argv[*arg_ptr] == NULL))
+ return false;
+ if (!check_name_arg("-contains", argv[*arg_ptr]))
+ return false;
+
+ our_pred = insert_primary (entry);
+ our_pred->need_stat = false;
+ our_pred->need_type = true;
+ our_pred->args.str = argv[*arg_ptr];
+ (*arg_ptr)++;
+ return true;
+}
+
+static boolean
parse_ctime (const struct parser_table* entry, char **argv, int *arg_ptr)
{
return insert_time (argv, arg_ptr, entry, pred_ctime);
@@ -793,11 +814,11 @@
--version -xdev -ignore_readdir_race -noignore_readdir_race\n"));
puts (_("\
tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
- -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
- -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex
PATTERN\n\
- -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE"));
+ -cnewer FILE -contains NAME -ctime N -empty -false -fstype TYPE -gid N\n\
+ -group NAME -ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN\n\
+ -iregex PATTERN -links N -lname PATTERN -mmin N -mtime N -name
PATTERN"));
puts (_("\
- -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
+ -newer FILE -nouser -nogroup -path PATTERN -perm [+-]MODE -regex
PATTERN\n\
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
-used N -user NAME -xtype [bcdpfls]\n"));
puts (_("\
diff -ru findutils-4.2.33/find/pred.c findutils-4.2.33-p/find/pred.c
--- findutils-4.2.33/find/pred.c 2007-12-08 06:00:47.000000000 -0800
+++ findutils-4.2.33-p/find/pred.c 2009-02-21 09:29:52.000000000 -0800
@@ -171,6 +171,7 @@
{pred_amin, "cmin "},
{pred_cnewer, "cnewer "},
{pred_comma, ", "},
+ {pred_contains, "contains "},
{pred_ctime, "ctime "},
{pred_delete, "delete "},
{pred_empty, "empty "},
@@ -376,6 +377,38 @@
}
boolean
+pred_contains (char *pathname, struct stat *stat_buf, struct predicate
*pred_ptr)
+{
+ mode_t mode;
+ char *fn;
+ struct stat contained;
+ int r;
+
+ assert(state.have_type);
+ assert(state.type != 0);
+
+ (void) pathname;
+
+ if (state.have_stat)
+ mode = stat_buf->st_mode;
+ else
+ mode = state.type;
+
+ if (!S_ISDIR (mode))
+ return (false);
+
+ fn = (char *) xmalloc (strlen(state.rel_pathname) +
strlen(pred_ptr->args.str) + 2);
+ if (!fn)
+ return (false);
+
+ sprintf (fn, "%s/%s", state.rel_pathname, pred_ptr->args.str);
+ r = lstat (fn, &contained);
+
+ free (fn);
+ return (r == 0 ? true : false);
+}
+
+boolean
pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
{
(void) &pathname;
- RFC: "-contains" option,
Eddie Kohler <=