There is no easy way to exclude mount points from the output of `find`. The options -xdev or -mount prevent `find` from traversing over the mount points but do not exclude the mount points themselves. It could be scripted by AWK on Linux as in the following example:
$ find / -xdev -maxdepth 1 $(awk '$2 != "/" { printf("! -path %s ", $2) }' /proc/mounts) Would it make sense to introduce a new predicate similar to -samefile that takes into account device numbers only? With the proposed predicate implemented in `find`, the above command could be encoded in a more user-friendly way: $ find / -xdev -maxdepth 1 -samedev / Originally reported at: https://bugzilla.redhat.com/1607772 --- find/defs.h | 1 + find/find.1 | 8 ++++++++ find/parser.c | 23 +++++++++++++++++++++++ find/pred.c | 18 ++++++++++++++++++ find/tree.c | 1 + 5 files changed, 51 insertions(+) diff --git a/find/defs.h b/find/defs.h index 63f3b2a3..2d4965e9 100644 --- a/find/defs.h +++ b/find/defs.h @@ -461,6 +461,7 @@ PREDICATEFUNCTION pred_print0; PREDICATEFUNCTION pred_prune; PREDICATEFUNCTION pred_readable; PREDICATEFUNCTION pred_regex; +PREDICATEFUNCTION pred_samedev; PREDICATEFUNCTION pred_samefile; PREDICATEFUNCTION pred_size; PREDICATEFUNCTION pred_true; diff --git a/find/find.1 b/find/find.1 index 67fdd537..dec78798 100644 --- a/find/find.1 +++ b/find/find.1 @@ -932,6 +932,13 @@ newline), but this can be changed with the .B \-regextype option. +.IP "\-samedev \fIname\fR" +File is on the same device as +.IR name . +When +.B \-L +is in effect, this can include symbolic links. + .IP "\-samefile \fIname\fR" File refers to the same inode as .IR name . @@ -2282,6 +2289,7 @@ Feature Added in Also occurs in \-exec ... + 4.2.12 POSIX \-execdir 4.2.12 BSD \-okdir 4.2.12 +\-samedev 4.6.1 \-samefile 4.2.11 \-H 4.2.5 POSIX \-L 4.2.5 POSIX diff --git a/find/parser.c b/find/parser.c index d6621506..14279c69 100644 --- a/find/parser.c +++ b/find/parser.c @@ -128,6 +128,7 @@ static bool parse_printf (const struct parser_table*, char *argv[], int * static bool parse_prune (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_regex (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_regextype (const struct parser_table*, char *argv[], int *arg_ptr); +static bool parse_samedev (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_samefile (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_size (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_time (const struct parser_table*, char *argv[], int *arg_ptr); @@ -290,6 +291,7 @@ static struct parser_table const parse_table[] = {ARG_TEST, "readable", parse_accesscheck, pred_readable}, /* GNU, 4.3.0+ */ PARSE_TEST ("regex", regex), /* GNU */ PARSE_POSOPT ("regextype", regextype), /* GNU */ + PARSE_TEST ("samedev", samedev), /* GNU */ PARSE_TEST ("samefile", samefile), /* GNU */ #if 0 PARSE_OPTION ("show-control-chars", show_control_chars), /* GNU, 4.3.0+ */ @@ -2169,6 +2171,27 @@ parse_size (const struct parser_table* entry, char **argv, int *arg_ptr) } +static bool +parse_samedev (const struct parser_table* entry, char **argv, int *arg_ptr) +{ + struct predicate *our_pred; + struct stat st; + const char *filename; + + set_stat_placeholders (&st); + if (!collect_arg_stat_info (argv, arg_ptr, &st, &filename)) + return false; + + our_pred = insert_primary (entry, filename); + our_pred->args.samefileid.ino = (ino_t) -1; + our_pred->args.samefileid.dev = st.st_dev; + our_pred->args.samefileid.fd = -1; + our_pred->need_type = false; + our_pred->need_stat = true; + our_pred->est_success_rate = 1.0f; + return true; +} + static bool parse_samefile (const struct parser_table* entry, char **argv, int *arg_ptr) { diff --git a/find/pred.c b/find/pred.c index 2014b5ab..f1da8669 100644 --- a/find/pred.c +++ b/find/pred.c @@ -118,6 +118,7 @@ struct pred_assoc pred_table[] = {pred_quit, "quit "}, {pred_readable, "readable "}, {pred_regex, "regex "}, + {pred_samedev, "samedev "}, {pred_samefile,"samefile "}, {pred_size, "size "}, {pred_true, "true "}, @@ -986,6 +987,23 @@ pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_p return (false); } +bool +pred_samedev (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) +{ + (void) pathname; + + /* Stat the file (if not already statted) to check the device number. */ + if (0 == get_statinfo (pathname, state.rel_pathname, stat_buf)) + { + return (stat_buf->st_dev == pred_ptr->args.samefileid.dev); + } + else + { + /* get_statinfo will already have emitted an error message. */ + return false; + } +} + bool pred_samefile (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) { diff --git a/find/tree.c b/find/tree.c index 5be88f2e..f5ccc943 100644 --- a/find/tree.c +++ b/find/tree.c @@ -972,6 +972,7 @@ static struct pred_cost_lookup costlookup[] = { pred_quit , NeedsNothing }, { pred_readable , NeedsAccessInfo }, { pred_regex , NeedsNothing }, + { pred_samedev , NeedsStatInfo }, { pred_samefile , NeedsStatInfo }, { pred_size , NeedsStatInfo }, { pred_true , NeedsNothing }, -- 2.17.2