]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
src/bin/grepc: Handle xargs(1) errors properly
authorAlejandro Colomar <alx@kernel.org>
Thu, 30 Oct 2025 23:58:42 +0000 (00:58 +0100)
committerAlejandro Colomar <alx@kernel.org>
Sun, 2 Nov 2025 17:52:55 +0000 (18:52 +0100)
'xargs grep' is hard, because grep(1) exits with a status of 1 for no
match, which is not an error, but xargs(1) takes that as an error, which
is confused with other errors.

This trick with sh(1) was suggested by Paul, and nicely solves this
problem.

We also need to change $opts to be a normal variable.

We can't export bash array variables, and passing them to sh(1) -c is
not great; escapes could be messed.  It's more robust to use a normal
variable.

Link: <https://lists.gnu.org/archive/html/bug-grep/2025-10/msg00029.html>
Suggested-by: Paul Eggert <eggert@cs.ucla.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
src/bin/grepc

index a1916dc49c4487814609105fa49ade81e82b4af8..205ffdbcbd091bec659a5ff34da4212d47e55f9a 100755 (executable)
@@ -234,23 +234,20 @@ patterns="$(mktemp -t grepc.patterns.XXXXXX)";
 ) >"$patterns";
 
 
-# shellcheck disable=SC2206  # We want only non-empty variables in the array.
-opts=($A $B $C $c $h $i $l -M $m $n);
+export opts="$A $B $C $c $h $i $l -M $m $n";
 
 
 if test -z "$*"; then
-       pcre2grep "${opts[@]}" -f "$patterns" || true;
+       # shellcheck disable=SC2086  # $opts may contain zero or more flags
+       pcre2grep $opts -f "$patterns" || test $? -eq 1;
 else
        find "$@" -type f -print0 \
        | if test -z "$c"; then
-               # shellcheck disable=SC2248  # $i may be -i or nothing.
-               xargs -0 grep -lZPI $i -- "$identifier" || true;
+               xargs -0 sh -c 'grep -lZPI $i -e "$0" -- "$@" || test $? -eq 1;' "$identifier";
        else
                cat;
        fi \
-       | {
-               xargs -0 pcre2grep "${opts[@]}" -f "$patterns" || true;
-       };
+       | xargs -0 sh -c 'pcre2grep $opts -f "$0" -- "$@" || test $? -eq 1;' "$patterns";
 fi \
 | if test "$r" = 'yes'; then
        perl -p -e 's/('"$identifier"')/\033[32m\1\033[0m/';