gnu/128645: teach grep -r to how to ignore directories

Bjoern A. Zeeb bzeeb+freebsd at zabbadoz.net
Thu Nov 6 03:50:01 PST 2008


>Number:         128645
>Category:       gnu
>Synopsis:       teach grep -r to how to ignore directories
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 06 11:50:00 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Bjoern A. Zeeb
>Release:        8.0-CURRENT
>Organization:
Zabbadoz.NeT
>Environment:
>Description:
With for example a SVN tree checked out grep -r is a pain as it also finds the .svn/* copies and thus gives duplicate results, ...

There is no way to tell grep to ignore .svn directories but only to ignore filenames based on patterns which works but not very well.
>How-To-Repeat:
checkout freebsd src tree from svn. From the toplevel do a
grep -r XXX-BZ sys/
>Fix:
I have a patch is not great but it adds an --exclude-dir option so one could do
  grep -r --exlcude-dir .svn XXX-BZ sys/

It would need review and someone brave enough to commit to gnu/ ;-)

The patch is under GPLv2.

Patch attached with submission follows:

Index: gnu/usr.bin/grep/savedir.c
===================================================================
--- gnu/usr.bin/grep/savedir.c	(revision 184265)
+++ gnu/usr.bin/grep/savedir.c	(working copy)
@@ -100,13 +100,34 @@
    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 *excluded_dirs_patterns)
 {
   DIR *dirp;
   struct dirent *dp;
   char *name_space;
   char *namep;
 
+  if (excluded_dirs_patterns && isdir (dir))
+    {
+      const char *d;
+
+      d = strrchr(dir, '/');
+      if (d != NULL)
+        d++;
+      else
+        d = dir;
+      if (excluded_filename (excluded_dirs_patterns, d, 0))
+        {
+          if (name_size < 2)
+            name_size = 2;
+          name_space = (char *) malloc (name_size);
+          if (name_space == NULL)
+            return NULL;
+          memset (name_space, '\0', name_size);
+          return name_space;
+        }
+    }
+
   dirp = opendir (dir);
   if (dirp == NULL)
     return NULL;
Index: gnu/usr.bin/grep/savedir.h
===================================================================
--- gnu/usr.bin/grep/savedir.h	(revision 184265)
+++ gnu/usr.bin/grep/savedir.h	(working copy)
@@ -13,6 +13,6 @@
 
 extern char *
 savedir PARAMS ((const char *dir, off_t name_size,
-		 struct exclude *, struct exclude *));
+    struct exclude *, struct exclude *, struct exclude *));
 
 #endif
Index: gnu/usr.bin/grep/grep.c
===================================================================
--- gnu/usr.bin/grep/grep.c	(revision 184265)
+++ gnu/usr.bin/grep/grep.c	(working copy)
@@ -89,6 +89,7 @@
 static const char *grep_color = "01;31";
 
 static struct exclude *excluded_patterns;
+static struct exclude *excluded_dirs_patterns;
 static struct exclude *included_patterns;
 /* Short options.  */
 static char const short_options[] =
@@ -103,7 +104,8 @@
   EXCLUDE_OPTION,
   EXCLUDE_FROM_OPTION,
   LINE_BUFFERED_OPTION,
-  LABEL_OPTION
+  LABEL_OPTION,
+  EXCLUDE_DIR_OPTION
 };
 
 /* Long options equivalences. */
@@ -122,6 +124,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'},
@@ -1065,7 +1068,7 @@
 	}
 
   name_space = savedir (dir, stats->stat.st_size, included_patterns,
-			excluded_patterns);
+			excluded_patterns, excluded_dirs_patterns);
 
   if (! name_space)
     {
@@ -1166,6 +1169,7 @@
   -R, -r, --recursive       equivalent to --directories=recurse\n\
       --include=PATTERN     files 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\
@@ -1685,6 +1689,12 @@
 	add_exclude (excluded_patterns, optarg);
 	break;
 
+      case EXCLUDE_DIR_OPTION:
+	if (!excluded_dirs_patterns)
+	  excluded_dirs_patterns = new_exclude ();
+	add_exclude (excluded_dirs_patterns, optarg);
+	break;
+
       case EXCLUDE_FROM_OPTION:
 	if (!excluded_patterns)
 	  excluded_patterns = new_exclude ();
@@ -1837,6 +1847,18 @@
 	do
 	{
 	  char *file = argv[optind];
+	  if (excluded_dirs_patterns && isdir (file))
+            {
+              char *d;
+
+              d = strrchr(file, '/');
+              if (d != NULL)
+                d++;
+              else
+                d = file;
+	      if (excluded_filename (excluded_dirs_patterns, d, 0))
+		continue;
+            } 
 	  if ((included_patterns || excluded_patterns)
 	      && !isdir (file))
 	    {


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list