From a77f3ecf68c63081934f5e0800eab80b5098bb24 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 15 Aug 2020 00:39:30 +0200 Subject: grep: for -L, exitcode 0 means files *without* matches were found, closes 13151 This is a recent change in GNU grep as well (after 3.1) function old new delta grep_file 1215 1228 +13 Signed-off-by: Denys Vlasenko --- findutils/grep.c | 29 ++++++++++++++--------------- testsuite/grep.tests | 8 ++++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/findutils/grep.c b/findutils/grep.c index 55e9c0a8f..b456ed467 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -167,13 +167,11 @@ enum { OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, }; -#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l) #define PRINT_LINE_NUM (option_mask32 & OPT_n) #define BE_QUIET (option_mask32 & OPT_q) #define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) #define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) #define FGREP_FLAG (option_mask32 & OPT_F) -#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) #define NUL_DELIMITED (option_mask32 & OPT_z) struct globals { @@ -476,13 +474,13 @@ static int grep_file(FILE *file) * even if errors were detected" */ exit(EXIT_SUCCESS); } - /* if we're just printing filenames, we stop after the first match */ - if (PRINT_FILES_WITH_MATCHES) { + /* -l "print filenames with matches": stop after the first match */ + if (option_mask32 & OPT_l) { puts(cur_file); - /* fall through to "return 1" */ + return 1; } - /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */ - return 1; /* one match */ + /* -L "print filenames without matches": return early too */ + return 0; /* 0: we do not print fname, hence it's "not a match" */ } #if ENABLE_FEATURE_GREP_CONTEXT @@ -602,15 +600,16 @@ static int grep_file(FILE *file) printf("%d\n", nmatches); } - /* grep -L: print just the filename */ - if (PRINT_FILES_WITHOUT_MATCHES) { + /* grep -L: "print filenames without matches" */ + if (option_mask32 & OPT_L) { /* nmatches is zero, no need to check it: - * we return 1 early if we detected a match - * and PRINT_FILES_WITHOUT_MATCHES is set */ + * we return 0 early if -L and we detect a match + */ puts(cur_file); + return 1; /* 1: we printed fname, hence it's "a match" */ } - return nmatches; + return nmatches != 0; /* we return not a count, but a boolean */ } #if ENABLE_FEATURE_CLEAN_UP @@ -687,7 +686,7 @@ static int FAST_FUNC file_action_grep(const char *filename, return 0; } cur_file = filename; - *(int*)matched += grep_file(file); + *(int*)matched |= grep_file(file); fclose(file); return 1; } @@ -844,7 +843,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { if (!(option_mask32 & OPT_h)) print_filename = 1; - matched += grep_dir(cur_file); + matched |= grep_dir(cur_file); goto grep_done; } } @@ -857,7 +856,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) continue; } } - matched += grep_file(file); + matched |= grep_file(file); fclose_if_not_stdin(file); grep_done: ; } while (*argv && *++argv); diff --git a/testsuite/grep.tests b/testsuite/grep.tests index e38278810..66498a989 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests @@ -96,6 +96,14 @@ testing "grep -x -F (partial match 1)" "grep -x -F foo input ; echo \$?" \ testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ "1\n" "bar foo\n" "" +# -L "show filenames which do not match" has inverted exitcode (if it printed something, it's "success") +testing "grep -L exitcode 0" "grep -L qwe input; echo \$?" \ + "input\n0\n" "asd\n" "" +testing "grep -L exitcode 0 #2" "grep -L qwe input -; echo \$?" \ + "(standard input)\n0\n" "qwe\n" "asd\n" +testing "grep -L exitcode 1" "grep -L qwe input; echo \$?" \ + "1\n" "qwe\n" "" + optional EGREP testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ "b\ar\nfoo\nbaz" -- cgit v1.2.3