Implement the following options and primaries:

-E      Interpret regular expressions followed by -regex and -iregex op-
             tions as extended (modern) regular expressions rather than basic
             regular expressions (BRE's).  The re_format(7) manual page fully
             describes both formats.

     -iname pattern
             Like -name, but the match is case insensitive.

     -ipath pattern
             Like -path, but the match is case insensitive.

     -regex pattern
             True if the whole path of the file matches pattern using regular
             expression.  To match a file named ``./foo/xyzzy'', you can use
             the regular expression ``.*/[xyz]*'' or ``.*/foo/.*'', but not
             ``xyzzy'' or ``/foo/''.

     -iregex pattern
             Like -regex, but the match is case insensitive.

These are meant to be compatible with other find(1) implementations
such as GNU's or NetBSD's except regexp library differences.

Reviewed by:	sobomax, dcs, and some other people on -current
This commit is contained in:
Akinori MUSHA 2001-02-23 16:20:55 +00:00
parent 0a3a912634
commit 7c1d4b3ae9
7 changed files with 219 additions and 7 deletions

View File

@ -63,7 +63,10 @@ PLAN *c_follow __P((void));
PLAN *c_fstype __P((char *));
#endif
PLAN *c_group __P((char *));
PLAN *c_iname __P((char *));
PLAN *c_inum __P((char *));
PLAN *c_ipath __P((char *));
PLAN *c_iregex __P((char *));
PLAN *c_links __P((char *));
PLAN *c_ls __P((void));
PLAN *c_name __P((char *));
@ -75,6 +78,7 @@ PLAN *c_perm __P((char *));
PLAN *c_print __P((void));
PLAN *c_print0 __P((void));
PLAN *c_prune __P((void));
PLAN *c_regex __P((char *));
PLAN *c_size __P((char *));
PLAN *c_type __P((char *));
PLAN *c_user __P((char *));
@ -90,3 +94,4 @@ PLAN *c_or __P((void));
extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs;
extern int mindepth, maxdepth;
extern int regexp_flags;

View File

@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl H | Fl L | Fl P
.Op Fl Xdsx
.Op Fl EXdsx
.Op Fl f Ar pathname
.Op Ar pathname ...\&
.Ar expression
@ -59,6 +59,15 @@ of each file in the tree.
The options are as follows:
.Pp
.Bl -tag -width Ds
.It Fl E
Interpret regular expressions followed by
.Ic -regex
and
.Ic -iregex
options as extended (modern) regular expressions rather than basic
regular expressions (BRE's). The
.Xr re_format 7
manual page fully describes both formats.
.It Fl H
The
.Fl H
@ -286,6 +295,20 @@ may be used as part of
.Ar pattern .
These characters may be matched explicitly by escaping them with a
backslash (``\e'').
.It Ic -iname Ar pattern
Like
.Ic -name ,
but the match is case insensitive.
.It Ic -regex Ar pattern
True if the whole path of the file matches
.Ar pattern
using regular expression. To match a file named ``./foo/xyzzy'', you
can use the regular expression ``.*/[xyz]*'' or ``.*/foo/.*'', but not
``xyzzy'' or ``/foo/''.
.It Ic -iregex Ar pattern
Like
.Ic -regex ,
but the match is case insensitive.
.It Ic -newer Ar file
True if the current file has a more recent last modification time than
.Ar file .
@ -303,6 +326,10 @@ These characters may be matched explicitly by escaping them with a
backslash (``\e'').
Slashes (``/'') are treated as normal characters and do not have to be
matched explicitly.
.It Ic -ipath Ar pattern
Like
.Ic -path ,
but the match is case insensitive.
.It Xo
.Ic -perm
.Oo Fl Oc Ns Ar mode
@ -487,6 +514,7 @@ Print out a list of all the files that are either owned by ``wnj'' or
that are newer than ``ttt''.
.El
.Sh SEE ALSO
.Xr re_format 7,
.Xr chflags 1 ,
.Xr chmod 1 ,
.Xr locate 1 ,
@ -506,11 +534,14 @@ utility syntax is a superset of the syntax specified by the
standard.
.Pp
All the single character options as well as the
.Ic -iname ,
.Ic -inum ,
.Ic -iregex ,
.Ic -print0 ,
.Ic -delete ,
.Ic -ls ,
and
.Ic -ls
.Ic -regex
primaries are extensions to
.St -p1003.2 .
.Pp
@ -540,6 +571,13 @@ primaries did not replace the string ``{}'' in the utility name or the
utility arguments if it had preceding or following non-whitespace characters.
This version replaces it no matter where in the utility name or arguments
it appears.
.Pp
The
.Fl E
option was implemented on the analogy of
.Xr grep 1
and
.Xr sed 1 .
.Sh BUGS
The special characters used by
.Nm

View File

@ -49,6 +49,7 @@ static const char rcsid[] =
#include <err.h>
#include <errno.h>
#include <fts.h>
#include <regex.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

View File

@ -37,14 +37,16 @@
* $FreeBSD$
*/
#include <regex.h>
/* node type */
enum ntype {
N_AND = 1, /* must start > 0 */
N_AMIN, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CTIME, N_DEPTH,
N_EMPTY, N_EXEC, N_EXECDIR, N_EXPR, N_FLAGS,
N_FOLLOW, N_FSTYPE, N_GROUP, N_INUM, N_LINKS, N_LS, N_MMIN,
N_MTIME, N_NAME,
N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR, N_PATH,
N_MTIME, N_NAME, N_INAME, N_PATH, N_IPATH, N_REGEX, N_IREGEX,
N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK, N_OPENPAREN, N_OR,
N_PERM, N_PRINT, N_PRUNE, N_SIZE, N_TYPE, N_USER, N_XDEV,
N_PRINT0, N_DELETE, N_MAXDEPTH, N_MINDEPTH
};
@ -85,6 +87,7 @@ typedef struct _plandata {
} ex;
char *_a_data[2]; /* array of char pointers */
char *_c_data; /* char pointer */
regex_t *_re_data; /* regex */
} p_un;
} PLAN;
#define a_data p_un._a_data
@ -100,6 +103,7 @@ typedef struct _plandata {
#define p_data p_un._p_data
#define t_data p_un._t_data
#define u_data p_un._u_data
#define re_data p_un._re_data
#define e_argv p_un.ex._e_argv
#define e_orig p_un.ex._e_orig
#define e_len p_un.ex._e_len

View File

@ -56,6 +56,7 @@ static const char rcsid[] =
#include <fts.h>
#include <grp.h>
#include <pwd.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -76,6 +77,8 @@ static const char rcsid[] =
} \
}
static int do_f_regex __P((PLAN *, FTSENT *, int));
static PLAN *do_c_regex __P((char *, int));
static PLAN *palloc __P((enum ntype, int (*) __P((PLAN *, FTSENT *))));
/*
@ -924,6 +927,133 @@ c_name(pattern)
return (new);
}
/*
* -iname functions --
*
* Like -iname, but the match is case insensitive.
*/
int
f_iname(plan, entry)
PLAN *plan;
FTSENT *entry;
{
return (!fnmatch(plan->c_data, entry->fts_name, FNM_CASEFOLD));
}
PLAN *
c_iname(pattern)
char *pattern;
{
PLAN *new;
new = palloc(N_INAME, f_iname);
new->c_data = pattern;
return (new);
}
/*
* -regex functions --
*
* True if the whole path of the file matches pattern using
* regular expression.
*/
int
f_regex(plan, entry)
PLAN *plan;
FTSENT *entry;
{
return (do_f_regex(plan, entry, 0));
}
PLAN *
c_regex(pattern)
char *pattern;
{
return (do_c_regex(pattern, 0));
}
/*
* -iregex functions --
*
* Like -regex, but the match is case insensitive.
*/
int
f_iregex(plan, entry)
PLAN *plan;
FTSENT *entry;
{
return (do_f_regex(plan, entry, REG_ICASE));
}
PLAN *
c_iregex(pattern)
char *pattern;
{
return (do_c_regex(pattern, REG_ICASE));
}
static int
do_f_regex(plan, entry, icase)
PLAN *plan;
FTSENT *entry;
int icase;
{
char *str;
size_t len;
regex_t *pre;
regmatch_t pmatch;
int errcode;
char errbuf[LINE_MAX];
int matched;
pre = plan->re_data;
str = entry->fts_path;
len = strlen(str);
matched = 0;
pmatch.rm_so = 0;
pmatch.rm_eo = len;
errcode = regexec(pre, str, 1, &pmatch, REG_STARTEND);
if (errcode != 0 && errcode != REG_NOMATCH) {
regerror(errcode, pre, errbuf, sizeof errbuf);
errx(1, "%s: %s",
icase == 0 ? "-regex" : "-iregex", errbuf);
}
if (errcode == 0 && pmatch.rm_so == 0 && pmatch.rm_eo == len)
matched = 1;
return (matched);
}
PLAN *
do_c_regex(pattern, icase)
char *pattern;
int icase;
{
PLAN *new;
regex_t *pre;
int errcode;
char errbuf[LINE_MAX];
if ((pre = malloc(sizeof(regex_t))) == NULL)
err(1, NULL);
if ((errcode = regcomp(pre, pattern, regexp_flags | icase)) != 0) {
regerror(errcode, pre, errbuf, sizeof errbuf);
errx(1, "%s: %s: %s",
icase == 0 ? "-regex" : "-iregex", pattern, errbuf);
}
new = icase == 0 ? palloc(N_REGEX, f_regex) : palloc(N_IREGEX, f_iregex);
new->re_data = pre;
return (new);
}
/*
* -newer file functions --
*
@ -1019,7 +1149,31 @@ c_path(pattern)
{
PLAN *new;
new = palloc(N_NAME, f_path);
new = palloc(N_PATH, f_path);
new->c_data = pattern;
return (new);
}
/*
* -ipath functions --
*
* Like -path, but the match is case insensitive.
*/
int
f_ipath(plan, entry)
PLAN *plan;
FTSENT *entry;
{
return (!fnmatch(plan->c_data, entry->fts_path, FNM_CASEFOLD));
}
PLAN *
c_ipath(pattern)
char *pattern;
{
PLAN *new;
new = palloc(N_IPATH, f_ipath);
new->c_data = pattern;
return (new);
}

View File

@ -57,6 +57,7 @@ static const char rcsid[] =
#include <fcntl.h>
#include <fts.h>
#include <locale.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@ -73,6 +74,7 @@ int isoutput; /* user specified output operator */
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 regexp_flags = REG_BASIC; /* use the "basic" regexp by default*/
static void usage __P((void));
@ -91,8 +93,11 @@ main(argc, argv)
p = start = argv;
Hflag = Lflag = 0;
ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
while ((ch = getopt(argc, argv, "HLPXdf:sx")) != -1)
while ((ch = getopt(argc, argv, "EHLPXdf:sx")) != -1)
switch (ch) {
case 'E':
regexp_flags |= REG_EXTENDED;
break;
case 'H':
Hflag = 1;
Lflag = 0;
@ -161,6 +166,6 @@ static void
usage()
{
(void)fprintf(stderr,
"usage: find [-H | -L | -P] [-Xdsx] [-f file] [file ...] [expression]\n");
"usage: find [-H | -L | -P] [-EXdsx] [-f file] [file ...] [expression]\n");
exit(1);
}

View File

@ -47,6 +47,7 @@ static const char rcsid[] =
#include <err.h>
#include <fts.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -82,7 +83,10 @@ static OPTION const options[] = {
{ "-fstype", N_FSTYPE, c_fstype, O_ARGV },
#endif
{ "-group", N_GROUP, c_group, O_ARGV },
{ "-iname", N_INAME, c_iname, O_ARGV },
{ "-inum", N_INUM, c_inum, O_ARGV },
{ "-ipath", N_IPATH, c_ipath, O_ARGV },
{ "-iregex", N_IREGEX, c_iregex, O_ARGV },
{ "-links", N_LINKS, c_links, O_ARGV },
{ "-ls", N_LS, c_ls, O_ZERO },
{ "-maxdepth", N_MAXDEPTH, c_maxdepth, O_ARGV },
@ -101,6 +105,7 @@ static OPTION const options[] = {
{ "-print", N_PRINT, c_print, O_ZERO },
{ "-print0", N_PRINT0, c_print0, O_ZERO },
{ "-prune", N_PRUNE, c_prune, O_ZERO },
{ "-regex", N_REGEX, c_regex, O_ARGV },
{ "-size", N_SIZE, c_size, O_ARGV },
{ "-type", N_TYPE, c_type, O_ARGV },
{ "-user", N_USER, c_user, O_ARGV },