>From 3b6896988c4e139115f24a2c6a804dbdb6bd744c Mon Sep 17 00:00:00 2001 From: Paul Eggert 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