? grep.diffX
Index: doc/grep.1
===================================================================
RCS file: /cvsroot/src/gnu/dist/grep/doc/grep.1,v
retrieving revision 1.10
diff -u -r1.10 grep.1
--- doc/grep.1	22 Apr 2003 16:17:39 -0000	1.10
+++ doc/grep.1	15 Nov 2004 20:56:49 -0000
@@ -328,10 +328,18 @@
 Recurse in directories only searching file matching
 .I PATTERN.
 .TP
+.BR "\fR \fP \-\^\-include-dir=" PATTERN
+Only recurse into directories matching
+.I PATTERN.
+.TP
 .BR "\fR \fP \-\^\-exclude=" PATTERN
 Recurse in directories skip file matching
 .I PATTERN.
 .TP
+.BR "\fR \fP \-\^\-exclude-dir=" PATTERN
+Skip recursing into directories matching
+.I PATTERN.
+.TP
 .BR \-s ", " \-\^\-no-messages
 Suppress error messages about nonexistent or unreadable files.
 Portability note: unlike \s-1GNU\s0
Index: doc/grep.texi
===================================================================
RCS file: /cvsroot/src/gnu/dist/grep/doc/grep.texi,v
retrieving revision 1.9
diff -u -r1.9 grep.texi
--- doc/grep.texi	29 Mar 2003 14:33:49 -0000	1.9
+++ doc/grep.texi	15 Nov 2004 20:56:53 -0000
@@ -418,7 +418,14 @@
 @cindex include files
 @cindex searching directory trees
 When processing directories recursively, only files matching @var{file_pattern}
-will be search.
+will be searched.
+
+@item --include-dir=@var{file_pattern}
+@opindex --include-dir
+@cindex include files
+@cindex searching directory trees
+When processing directories recursively, only directories matching
+@var{file_pattern} will be searched.
 
 @item --exclude=@var{file_pattern}
 @opindex --exclude
@@ -426,6 +433,13 @@
 @cindex searching directory trees
 When processing directories recursively, skip files matching @var{file_pattern}.
 
+@item --exclude-dir=@var{file_pattern}
+@opindex --exclude-dir
+@cindex exclude files
+@cindex searching directory trees
+When processing directories recursively, skip directories matching
+@var{file_pattern}.
+
 @item -m @var{num}
 @itemx --max-count=@var{num}
 @opindex -m
Index: lib/savedir.c
===================================================================
RCS file: /cvsroot/src/gnu/dist/grep/lib/savedir.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 savedir.c
--- lib/savedir.c	26 Jan 2003 23:15:13 -0000	1.1.1.1
+++ lib/savedir.c	15 Nov 2004 20:56:53 -0000
@@ -102,7 +102,9 @@
    Return NULL if DIR cannot be opened or if out of memory. */
 char *
 savedir (const char *dir, off_t name_size, struct exclude *included_patterns,
-	 struct exclude *excluded_patterns)
+	 struct exclude *excluded_patterns,
+	struct exclude *included_dir_patterns,
+	struct exclude *excluded_dir_patterns)
 {
   DIR *dirp;
   struct dirent *dp;
@@ -146,6 +148,17 @@
 		continue;
 	    }
 
+		if ((included_dir_patterns || excluded_dir_patterns) &&
+		    isdir1(dir, dp->d_name))
+		{
+			if (included_dir_patterns &&
+			    !excluded_filename(included_dir_patterns, dp->d_name, 0))
+				continue;
+			if (excluded_dir_patterns &&
+			    excluded_filename(excluded_dir_patterns, dp->d_name, 0))
+				continue;
+		}
+
 	  if (size_needed > name_size)
 	    {
 	      char *new_name_space;
Index: lib/savedir.h
===================================================================
RCS file: /cvsroot/src/gnu/dist/grep/lib/savedir.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 savedir.h
--- lib/savedir.h	26 Jan 2003 23:15:13 -0000	1.1.1.1
+++ lib/savedir.h	15 Nov 2004 20:56:53 -0000
@@ -15,6 +15,7 @@
 
 extern char *
 savedir PARAMS ((const char *dir, off_t name_size,
+		 struct exclude *, struct exclude *,
 		 struct exclude *, struct exclude *));
 
 #endif
Index: src/grep.c
===================================================================
RCS file: /cvsroot/src/gnu/dist/grep/src/grep.c,v
retrieving revision 1.10
diff -u -r1.10 grep.c
--- src/grep.c	13 Feb 2003 07:48:12 -0000	1.10
+++ src/grep.c	15 Nov 2004 20:56:54 -0000
@@ -80,6 +80,8 @@
 
 static struct exclude *excluded_patterns;
 static struct exclude *included_patterns;
+static struct exclude *excluded_dir_patterns;
+static struct exclude *included_dir_patterns;
 /* Short options.  */
 static char const short_options[] =
 "0123456789A:B:C:D:EFGHIPUVX:abcd:e:f:hiKLlm:noqRrsuvwxyZz";
@@ -91,6 +93,8 @@
   COLOR_OPTION,
   INCLUDE_OPTION,
   EXCLUDE_OPTION,
+  INCLUDE_DIR_OPTION,
+  EXCLUDE_DIR_OPTION,
   EXCLUDE_FROM_OPTION,
   LINE_BUFFERED_OPTION,
   LABEL_OPTION
@@ -112,6 +116,7 @@
   {"directories", required_argument, NULL, 'd'},
   {"extended-regexp", no_argument, NULL, 'E'},
   {"exclude", required_argument, NULL, EXCLUDE_OPTION},
+  {"exclude-dir", required_argument, NULL, EXCLUDE_DIR_OPTION},
   {"exclude-from", required_argument, NULL, EXCLUDE_FROM_OPTION},
   {"file", required_argument, NULL, 'f'},
   {"files-with-matches", no_argument, NULL, 'l'},
@@ -120,6 +125,7 @@
   {"fixed-strings", no_argument, NULL, 'F'},
   {"help", no_argument, &show_help, 1},
   {"include", required_argument, NULL, INCLUDE_OPTION},
+  {"include-dir", required_argument, NULL, INCLUDE_DIR_OPTION},
   {"ignore-case", no_argument, NULL, 'i'},
   {"label", required_argument, NULL, LABEL_OPTION},
   {"line-buffered", no_argument, NULL, LINE_BUFFERED_OPTION},
@@ -1004,7 +1010,8 @@
 	}
 
   name_space = savedir (dir, stats->stat.st_size, included_patterns,
-			excluded_patterns);
+			excluded_patterns,
+                        included_dir_patterns, excluded_dir_patterns);
 
   if (! name_space)
     {
@@ -1102,7 +1109,9 @@
                             ACTION is 'read' or 'skip'\n\
   -R, -r, --recursive       equivalent to --directories=recurse\n\
       --include=PATTERN     files that match PATTERN will be examined\n\
+      --include-dir=PATTERN directories that match PATTERN will be examined.\n\
       --exclude=PATTERN     files that match PATTERN will be skipped.\n\
+      --exclude-dir=PATTERN directories that match PATTERN will be skipped.\n\
       --exclude-from=FILE   files that match PATTERN in FILE will be skipped.\n\
   -L, --files-without-match only print FILE names containing no match\n\
   -l, --files-with-matches  only print FILE names containing matches\n\
@@ -1596,6 +1605,12 @@
         }
 	break;
 
+		case EXCLUDE_DIR_OPTION:
+			if (!excluded_dir_patterns)
+				excluded_dir_patterns = new_exclude ();
+			add_exclude (excluded_dir_patterns, optarg);
+			break;
+
       case EXCLUDE_OPTION:
 	if (!excluded_patterns)
 	  excluded_patterns = new_exclude ();
@@ -1612,6 +1627,12 @@
           }
         break;
 
+		case INCLUDE_DIR_OPTION:
+			if (!included_dir_patterns)
+				included_dir_patterns = new_exclude ();
+			add_exclude (included_dir_patterns, optarg);
+			break;
+
       case INCLUDE_OPTION:
 	if (!included_patterns)
 	  included_patterns = new_exclude ();
@@ -1737,6 +1758,17 @@
 		  excluded_filename (excluded_patterns, file, 0))
 		continue;
 	    }
+
+		if ((included_dir_patterns || excluded_dir_patterns) &&
+		    isdir(file))
+		{
+			if (included_dir_patterns &&
+			    !excluded_filename(included_dir_patterns, file, 0))
+				continue;
+			if (excluded_dir_patterns &&
+			    excluded_filename(excluded_dir_patterns, file, 0))
+				continue;
+		}
 	  status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
 			      &stats_base);
 	}
