summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2008-03-08 17:13:02 +0000
committerph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>2008-03-08 17:13:02 +0000
commit2d6ec30227035d99946e622ed3ea3b4c26d415b3 (patch)
tree6f8ff5a681ccb3595b30908739e2060821409eb5
parentfcda7306390d18a5c931c65f378982ac84d8f58e (diff)
downloadpcre-2d6ec30227035d99946e622ed3ea3b4c26d415b3.tar.gz
Add --include_dir and --exclude_dir to pcregrep.
git-svn-id: svn://vcs.exim.org/pcre/code/trunk@325 2f5784b3-3f2a-0410-8824-cb99058d5e15
-rw-r--r--ChangeLog3
-rwxr-xr-xRunGrepTest4
-rw-r--r--doc/pcregrep.142
-rw-r--r--pcregrep.c67
4 files changed, 91 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 6e11941..5cc4838 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,9 @@ Version 7.7 05-Mar-08
pcregrep specification - which I improved to make it absolutely clear).
The action now is always to scan all levels of directory, and just
apply the include/exclude patterns to regular files.
+
+5. Added the --include_dir and --exclude_dir patterns to pcregrep, and used
+ --exclude_dir in the tests to avoid scanning .svn directories.
Version 7.6 28-Jan-08
diff --git a/RunGrepTest b/RunGrepTest
index 6f295b7..2d87541 100755
--- a/RunGrepTest
+++ b/RunGrepTest
@@ -147,11 +147,11 @@ echo "---------------------------- Test 34 -----------------------------" >>test
echo "RC=$?" >>testtry
echo "---------------------------- Test 35 -----------------------------" >>testtry
-(cd $srcdir; $valgrind $pcregrep -L -r --include=grepinputx 'fox' ./testdata) >>testtry
+(cd $srcdir; $valgrind $pcregrep -L -r --include=grepinputx --exclude_dir='^\.' 'fox' ./testdata) >>testtry
echo "RC=$?" >>testtry
echo "---------------------------- Test 36 -----------------------------" >>testtry
-(cd $srcdir; $valgrind $pcregrep -L -r --include=grepinput --exclude 'grepinput$' 'fox' ./testdata | sort) >>testtry
+(cd $srcdir; $valgrind $pcregrep -L -r --include=grepinput --exclude 'grepinput$' --exclude_dir='^\.' 'fox' ./testdata | sort) >>testtry
echo "RC=$?" >>testtry
echo "---------------------------- Test 37 -----------------------------" >>testtry
diff --git a/doc/pcregrep.1 b/doc/pcregrep.1
index 81ce05e..8803cf1 100644
--- a/doc/pcregrep.1
+++ b/doc/pcregrep.1
@@ -158,11 +158,21 @@ that matched.
\fB--exclude\fP=\fIpattern\fP
When \fBpcregrep\fP is searching the files in a directory as a consequence of
the \fB-r\fP (recursive search) option, any regular files whose names match the
-pattern are excluded (subdirectories are not excluded; they are searched
-recursively). The pattern is a PCRE regular expression, and is matched against
-the final component of the file name (not the entire path). If a file name
-matches both \fB--include\fP and \fB--exclude\fP, it is excluded. There is no
-short form for this option.
+pattern are excluded. Subdirectories are not excluded by this option; they are
+searched recursively, subject to the \fB--exclude_dir\fP and
+\fB--include_dir\fP options. The pattern is a PCRE regular expression, and is
+matched against the final component of the file name (not the entire path). If
+a file name matches both \fB--include\fP and \fB--exclude\fP, it is excluded.
+There is no short form for this option.
+.TP
+\fB--exclude_dir\fP=\fIpattern\fP
+When \fBpcregrep\fP is searching the contents of a directory as a consequence
+of the \fB-r\fP (recursive search) option, any subdirectories whose names match
+the pattern are excluded. (Note that the \fP--exclude\fP option does not affect
+subdirectories.) The pattern is a PCRE regular expression, and is matched
+against the final component of the name (not the entire path). If a
+subdirectory name matches both \fB--include_dir\fP and \fB--exclude_dir\fP, it
+is excluded. There is no short form for this option.
.TP
\fB-F\fP, \fB--fixed-strings\fP
Interpret each pattern as a list of fixed strings, separated by newlines,
@@ -215,11 +225,21 @@ Ignore upper/lower case distinctions during comparisons.
\fB--include\fP=\fIpattern\fP
When \fBpcregrep\fP is searching the files in a directory as a consequence of
the \fB-r\fP (recursive search) option, only those regular files whose names
-match the pattern are included (but subdirectories are always included and
-searched recursively). The pattern is a PCRE regular expression, and is matched
-against the final component of the file name (not the entire path). If a file
-name matches both \fB--include\fP and \fB--exclude\fP, it is excluded. There is
-no short form for this option.
+match the pattern are included. Subdirectories are always included and searched
+recursively, subject to the \fP--include_dir\fP and \fB--exclude_dir\fP
+options. The pattern is a PCRE regular expression, and is matched against the
+final component of the file name (not the entire path). If a file name matches
+both \fB--include\fP and \fB--exclude\fP, it is excluded. There is no short
+form for this option.
+.TP
+\fB--include_dir\fP=\fIpattern\fP
+When \fBpcregrep\fP is searching the contents of a directory as a consequence
+of the \fB-r\fP (recursive search) option, only those subdirectories whose
+names match the pattern are included. (Note that the \fB--include\fP option
+does not affect subdirectories.) The pattern is a PCRE regular expression, and
+is matched against the final component of the name (not the entire path). If a
+subdirectory name matches both \fB--include_dir\fP and \fB--exclude_dir\fP, it
+is excluded. There is no short form for this option.
.TP
\fB-L\fP, \fB--files-without-match\fP
Instead of outputting lines from the files, just output the names of the files
@@ -438,6 +458,6 @@ Cambridge CB2 3QH, England.
.rs
.sp
.nf
-Last updated: 07 March 2008
+Last updated: 08 March 2008
Copyright (c) 1997-2008 University of Cambridge.
.fi
diff --git a/pcregrep.c b/pcregrep.c
index 608e2a4..afecb07 100644
--- a/pcregrep.c
+++ b/pcregrep.c
@@ -139,9 +139,13 @@ static pcre_extra **hints_list = NULL;
static char *include_pattern = NULL;
static char *exclude_pattern = NULL;
+static char *include_dir_pattern = NULL;
+static char *exclude_dir_pattern = NULL;
static pcre *include_compiled = NULL;
static pcre *exclude_compiled = NULL;
+static pcre *include_dir_compiled = NULL;
+static pcre *exclude_dir_compiled = NULL;
static int after_context = 0;
static int before_context = 0;
@@ -181,15 +185,17 @@ typedef struct option_item {
/* Options without a single-letter equivalent get a negative value. This can be
used to identify them. */
-#define N_COLOUR (-1)
-#define N_EXCLUDE (-2)
-#define N_HELP (-3)
-#define N_INCLUDE (-4)
-#define N_LABEL (-5)
-#define N_LOCALE (-6)
-#define N_NULL (-7)
-#define N_LOFFSETS (-8)
-#define N_FOFFSETS (-9)
+#define N_COLOUR (-1)
+#define N_EXCLUDE (-2)
+#define N_EXCLUDE_DIR (-3)
+#define N_HELP (-4)
+#define N_INCLUDE (-5)
+#define N_INCLUDE_DIR (-6)
+#define N_LABEL (-7)
+#define N_LOCALE (-8)
+#define N_NULL (-9)
+#define N_LOFFSETS (-10)
+#define N_FOFFSETS (-11)
static option_item optionlist[] = {
{ OP_NODATA, N_NULL, NULL, "", " terminate options" },
@@ -222,6 +228,8 @@ static option_item optionlist[] = {
{ OP_NODATA, 'r', NULL, "recursive", "recursively scan sub-directories" },
{ OP_STRING, N_EXCLUDE,&exclude_pattern, "exclude=pattern","exclude matching files when recursing" },
{ OP_STRING, N_INCLUDE,&include_pattern, "include=pattern","include matching files when recursing" },
+ { OP_STRING, N_EXCLUDE_DIR,&exclude_dir_pattern, "exclude_dir=pattern","exclude matching directories when recursing" },
+ { OP_STRING, N_INCLUDE_DIR,&include_dir_pattern, "include_dir=pattern","include matching directories when recursing" },
#ifdef JFRIEDL_DEBUG
{ OP_OP_NUMBER, 'S', &S_arg, "jeffS", "replace matched (sub)string with X" },
#endif
@@ -1361,8 +1369,9 @@ if (strcmp(pathname, "-") == 0)
}
/* If the file is a directory, skip if skipping or if we are recursing, scan
-each file within it, subject to any include or exclude patterns that were set.
-The scanning code is localized so it can be made system-specific. */
+each file and directory within it, subject to any include or exclude patterns
+that were set. The scanning code is localized so it can be made
+system-specific. */
if ((sep = isdirectory(pathname)) != 0)
{
@@ -1387,7 +1396,17 @@ if ((sep = isdirectory(pathname)) != 0)
sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile);
nflen = strlen(nextfile);
- if (!isdirectory(buffer))
+ if (isdirectory(buffer))
+ {
+ if (exclude_dir_compiled != NULL &&
+ pcre_exec(exclude_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
+ continue;
+
+ if (include_dir_compiled != NULL &&
+ pcre_exec(include_dir_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) < 0)
+ continue;
+ }
+ else
{
if (exclude_compiled != NULL &&
pcre_exec(exclude_compiled, NULL, nextfile, nflen, 0, 0, NULL, 0) >= 0)
@@ -2292,6 +2311,30 @@ if (include_pattern != NULL)
}
}
+if (exclude_dir_pattern != NULL)
+ {
+ exclude_dir_compiled = pcre_compile(exclude_dir_pattern, 0, &error, &errptr,
+ pcretables);
+ if (exclude_dir_compiled == NULL)
+ {
+ fprintf(stderr, "pcregrep: Error in 'exclude_dir' regex at offset %d: %s\n",
+ errptr, error);
+ goto EXIT2;
+ }
+ }
+
+if (include_dir_pattern != NULL)
+ {
+ include_dir_compiled = pcre_compile(include_dir_pattern, 0, &error, &errptr,
+ pcretables);
+ if (include_dir_compiled == NULL)
+ {
+ fprintf(stderr, "pcregrep: Error in 'include_dir' regex at offset %d: %s\n",
+ errptr, error);
+ goto EXIT2;
+ }
+ }
+
/* If there are no further arguments, do the business on stdin and exit. */
if (i >= argc)