Aron Griffis wrote:
This generates output:
$ grep -rl --exclude-dir=usr LINUX /usr/include
and this doesn't:
$ grep -rl --exclude-dir='usr*' LINUX /usr/include
This feels like a bug.
Thanks for reporting that. I installed the attached patch.
>From 3b6896988c4e139115f24a2c6a804dbdb6bd744c Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Mon, 13 Jul 2015 16:31:26 -0700
Subject: [PATCH] grep: fix bug with --exclude-dir and command line
Reported by Aron Griffis in: http://bugs.gnu.org/21027
* NEWS: Document this.
* src/grep.c (grepdirent): Don't check whether the file is skipped
when on the command line, as that's the caller's responsibility.
(main): Anchor the exclude patterns.
* tests/include-exclude: Adjust test case to match fixed behavior.
Add some more test cases.
---
NEWS | 4 ++++
src/grep.c | 14 ++++++++------
tests/include-exclude | 12 +++++++++++-
3 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/NEWS b/NEWS
index 35c4aad..47b86ae 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,10 @@ GNU grep NEWS -*- outline -*-
'grep -D skip PATTERN FILE' no longer hangs if FILE is a fifo.
[bug introduced in grep-2.12]
+ --exclude and related options are now matched against entire
+ command-line arguments, not against command-line components.
+ [bug introduced in grep-2.6]
+
* Noteworthy changes in release 2.21 (2014-11-23) [stable]
diff --git a/src/grep.c b/src/grep.c
index a735ea5..d8ea70f 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -1482,9 +1482,10 @@ grepdirent (FTS *fts, FTSENT *ent, bool command_line)
return true;
}
- if (skipped_file (ent->fts_name, command_line,
- (ent->fts_info == FTS_D || ent->fts_info == FTS_DC
- || ent->fts_info == FTS_DNR)))
+ if (!command_line
+ && skipped_file (ent->fts_name, false,
+ (ent->fts_info == FTS_D || ent->fts_info == FTS_DC
+ || ent->fts_info == FTS_DNR)))
{
fts_set (fts, ent, FTS_SKIP);
return true;
@@ -2448,14 +2449,14 @@ main (int argc, char **argv)
if (!excluded_patterns)
excluded_patterns = new_exclude ();
add_exclude (excluded_patterns, optarg,
- (EXCLUDE_WILDCARDS
+ (EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS
| (opt == INCLUDE_OPTION ? EXCLUDE_INCLUDE : 0)));
break;
case EXCLUDE_FROM_OPTION:
if (!excluded_patterns)
excluded_patterns = new_exclude ();
if (add_exclude_file (add_exclude, excluded_patterns, optarg,
- EXCLUDE_WILDCARDS, '\n') != 0)
+ EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS, '\n') != 0)
{
error (EXIT_TROUBLE, errno, "%s", optarg);
}
@@ -2465,7 +2466,8 @@ main (int argc, char **argv)
if (!excluded_directory_patterns)
excluded_directory_patterns = new_exclude ();
strip_trailing_slashes (optarg);
- add_exclude (excluded_directory_patterns, optarg, EXCLUDE_WILDCARDS);
+ add_exclude (excluded_directory_patterns, optarg,
+ EXCLUDE_ANCHORED | EXCLUDE_WILDCARDS);
break;
case GROUP_SEPARATOR_OPTION:
diff --git a/tests/include-exclude b/tests/include-exclude
index 55819c5..8b2f5aa 100755
--- a/tests/include-exclude
+++ b/tests/include-exclude
@@ -14,6 +14,7 @@ printf '%s\n' x/a:aaa x/b:bbb > exp-not-dir || framework_failure_
printf '%s\n' x/a:aaa > exp-a || framework_failure_
printf '%s\n' a:aaa > exp-aa || framework_failure_
printf '%s\n' aaa > exp-aaa || framework_failure_
+printf '%s\n' ./x/a ./x/b ./x/dir/d > exp-dotnames || framework_failure+
grep -r --exclude='a*' . x > out || fail=1
sort out > k && mv k out
@@ -51,7 +52,7 @@ grep -r --include='a*' . x > out || fail=1
compare exp-a out || fail=1
# --include (without --recursive) uses different code
-grep --directories=skip --include=a --exclude-dir=dir '^aaa$' x/* > out \
+grep --directories=skip --include=x/a --exclude-dir=dir '^aaa$' x/* > out \
|| fail=1
compare exp-a out || fail=1
@@ -61,4 +62,13 @@ compare exp-aa out || fail=1
grep --exclude=- '^aaa$' - < x/a > out || fail=1
compare exp-aaa out || fail=1
+for exclude in 'x' 'x*'; do
+ grep -rl --exclude-dir="$exclude" . x > out
+ test $? -eq 1 || fail=1
+ compare /dev/null out || fail=1
+
+ grep -rl --exclude-dir="$exclude" . ./x > out || fail=1
+ compare exp-dotnames out || fail=1
+done
+
Exit $fail
--
2.1.0