diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-08-15 00:39:30 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-08-15 00:39:30 +0200 |
commit | a77f3ecf68c63081934f5e0800eab80b5098bb24 (patch) | |
tree | b8d9b333378f24b92feb2c38ea1552e465dca96d | |
parent | 5c69ad0ecdc18cf51b312c7c82848f4438fe1c8d (diff) | |
download | busybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.tar.gz busybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.tar.bz2 busybox-w32-a77f3ecf68c63081934f5e0800eab80b5098bb24.zip |
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 <vda.linux@googlemail.com>
-rw-r--r-- | findutils/grep.c | 29 | ||||
-rwxr-xr-x | 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 { | |||
167 | OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, | 167 | OPT_z = IF_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | #define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l) | ||
171 | #define PRINT_LINE_NUM (option_mask32 & OPT_n) | 170 | #define PRINT_LINE_NUM (option_mask32 & OPT_n) |
172 | #define BE_QUIET (option_mask32 & OPT_q) | 171 | #define BE_QUIET (option_mask32 & OPT_q) |
173 | #define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) | 172 | #define SUPPRESS_ERR_MSGS (option_mask32 & OPT_s) |
174 | #define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) | 173 | #define PRINT_MATCH_COUNTS (option_mask32 & OPT_c) |
175 | #define FGREP_FLAG (option_mask32 & OPT_F) | 174 | #define FGREP_FLAG (option_mask32 & OPT_F) |
176 | #define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) | ||
177 | #define NUL_DELIMITED (option_mask32 & OPT_z) | 175 | #define NUL_DELIMITED (option_mask32 & OPT_z) |
178 | 176 | ||
179 | struct globals { | 177 | struct globals { |
@@ -476,13 +474,13 @@ static int grep_file(FILE *file) | |||
476 | * even if errors were detected" */ | 474 | * even if errors were detected" */ |
477 | exit(EXIT_SUCCESS); | 475 | exit(EXIT_SUCCESS); |
478 | } | 476 | } |
479 | /* if we're just printing filenames, we stop after the first match */ | 477 | /* -l "print filenames with matches": stop after the first match */ |
480 | if (PRINT_FILES_WITH_MATCHES) { | 478 | if (option_mask32 & OPT_l) { |
481 | puts(cur_file); | 479 | puts(cur_file); |
482 | /* fall through to "return 1" */ | 480 | return 1; |
483 | } | 481 | } |
484 | /* OPT_L aka PRINT_FILES_WITHOUT_MATCHES: return early */ | 482 | /* -L "print filenames without matches": return early too */ |
485 | return 1; /* one match */ | 483 | return 0; /* 0: we do not print fname, hence it's "not a match" */ |
486 | } | 484 | } |
487 | 485 | ||
488 | #if ENABLE_FEATURE_GREP_CONTEXT | 486 | #if ENABLE_FEATURE_GREP_CONTEXT |
@@ -602,15 +600,16 @@ static int grep_file(FILE *file) | |||
602 | printf("%d\n", nmatches); | 600 | printf("%d\n", nmatches); |
603 | } | 601 | } |
604 | 602 | ||
605 | /* grep -L: print just the filename */ | 603 | /* grep -L: "print filenames without matches" */ |
606 | if (PRINT_FILES_WITHOUT_MATCHES) { | 604 | if (option_mask32 & OPT_L) { |
607 | /* nmatches is zero, no need to check it: | 605 | /* nmatches is zero, no need to check it: |
608 | * we return 1 early if we detected a match | 606 | * we return 0 early if -L and we detect a match |
609 | * and PRINT_FILES_WITHOUT_MATCHES is set */ | 607 | */ |
610 | puts(cur_file); | 608 | puts(cur_file); |
609 | return 1; /* 1: we printed fname, hence it's "a match" */ | ||
611 | } | 610 | } |
612 | 611 | ||
613 | return nmatches; | 612 | return nmatches != 0; /* we return not a count, but a boolean */ |
614 | } | 613 | } |
615 | 614 | ||
616 | #if ENABLE_FEATURE_CLEAN_UP | 615 | #if ENABLE_FEATURE_CLEAN_UP |
@@ -687,7 +686,7 @@ static int FAST_FUNC file_action_grep(const char *filename, | |||
687 | return 0; | 686 | return 0; |
688 | } | 687 | } |
689 | cur_file = filename; | 688 | cur_file = filename; |
690 | *(int*)matched += grep_file(file); | 689 | *(int*)matched |= grep_file(file); |
691 | fclose(file); | 690 | fclose(file); |
692 | return 1; | 691 | return 1; |
693 | } | 692 | } |
@@ -844,7 +843,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) | |||
844 | if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { | 843 | if (stat(cur_file, &st) == 0 && S_ISDIR(st.st_mode)) { |
845 | if (!(option_mask32 & OPT_h)) | 844 | if (!(option_mask32 & OPT_h)) |
846 | print_filename = 1; | 845 | print_filename = 1; |
847 | matched += grep_dir(cur_file); | 846 | matched |= grep_dir(cur_file); |
848 | goto grep_done; | 847 | goto grep_done; |
849 | } | 848 | } |
850 | } | 849 | } |
@@ -857,7 +856,7 @@ int grep_main(int argc UNUSED_PARAM, char **argv) | |||
857 | continue; | 856 | continue; |
858 | } | 857 | } |
859 | } | 858 | } |
860 | matched += grep_file(file); | 859 | matched |= grep_file(file); |
861 | fclose_if_not_stdin(file); | 860 | fclose_if_not_stdin(file); |
862 | grep_done: ; | 861 | grep_done: ; |
863 | } while (*argv && *++argv); | 862 | } 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 \$?" \ | |||
96 | testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ | 96 | testing "grep -x -F (partial match 2)" "grep -x -F foo input ; echo \$?" \ |
97 | "1\n" "bar foo\n" "" | 97 | "1\n" "bar foo\n" "" |
98 | 98 | ||
99 | # -L "show filenames which do not match" has inverted exitcode (if it printed something, it's "success") | ||
100 | testing "grep -L exitcode 0" "grep -L qwe input; echo \$?" \ | ||
101 | "input\n0\n" "asd\n" "" | ||
102 | testing "grep -L exitcode 0 #2" "grep -L qwe input -; echo \$?" \ | ||
103 | "(standard input)\n0\n" "qwe\n" "asd\n" | ||
104 | testing "grep -L exitcode 1" "grep -L qwe input; echo \$?" \ | ||
105 | "1\n" "qwe\n" "" | ||
106 | |||
99 | optional EGREP | 107 | optional EGREP |
100 | testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ | 108 | testing "grep -E supports extended regexps" "grep -E fo+" "foo\n" "" \ |
101 | "b\ar\nfoo\nbaz" | 109 | "b\ar\nfoo\nbaz" |