Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Got exit code 123 in find + xargs grep

Tags:

find

bash

xargs

Here is my script

eval "find \\( -type f -a \\( -name '*.h' \\) \\) -print0" | xargs -0 -n100 grep  -f <(echo "stdio")
echo $?

Nothing is found and the exit code is 123.

If I modify it a little as follows

echo "stdio" >.P
eval "find \\( -type f -a \\( -name '*.h' \\) \\) -print0" | xargs -0 -n100 grep <.P
echo $?

Something is found but the exit code is still 123.

So what is wrong?

======================================================================

Actually I just want to write a small script to make find+xargs+grep easier. For exmaple,
xgrep -e PATTERN1 -e PATTERN2 ... *.c *.h
is to execute
find -name *.c -o -name *.h|xargs grep -f <(echo "$PATTEN1
$PATTERN2")

Use -f option instead of -e is to avoid troubles in escaping single or double quations within the patterns.

#!/bin/bash
#set -e -o pipefail

eval ARGV=($(getopt -l '' -o 'e:li' -- "$@")) || exit 1
for((i=0;i<${#ARGV[@]};i++)) {
    o="${ARGV[$i]}"
    case $o in
    -e)
        i=$((i+1));
        a="${ARGV[$i]}"
        if [ -n "$grep_patterns" ]; then
            grep_patterns="$grep_patterns"$'\n'
        fi
        grep_patterns="$grep_patterns$a"
        ;;
    -i)
        grep_options="$grep_options -i"
        ;;
    -l)
        grep_options="$grep_options -l"
        ;;
    --)
        i=$((i+1));
        break;;
    esac
}

for((;i<${#ARGV[@]};i++)) {
    if [ -n "$find_options" ]; then
        find_options="$find_options -o "
    fi
    find_options="${find_options}-name '${ARGV[$i]}'"
}

cmd="find \\( -type f -a \\( $find_options \\) \\) -print0"
eval "$cmd" | xargs -0 grep $grep_options -f <(echo "$grep_patterns")
like image 864
Pan Ruochen Avatar asked Oct 24 '14 03:10

Pan Ruochen


1 Answers

123 means "any invocation exited with a non-zero status". So xargs ran grep at least twice (because you fed it so many files that they would exceed the maximum command line length, which you limited to 100 files) and at least one of the invocations was on a set of files which contained no matches, which caused the exit code from grep to be nonzero (failure).

Perhaps you should explain what you are trying to accomplish. The eval looks superfluous and the double redirection is probably not accomplishing what you want (grep's standard input cannot simultaneously be connected to the pipe from eval and to .P).

If you want to parametrize the first argument to grep, maybe do something like

#!/bin/sh
find -type f -name '*.h' -print0 |
xargs -0 -n100 grep "$1"

... where you invoke this with e.g. stdio as the first argument.

(Notice also the much simplified parameters to find. You only have two predicates so there is no need to parenthesize anything, and then the -a can be dropped, too.)

The exit code will still be 123 if there are grep invocations which return zero matches. You can reduce the chances by omitting the -n 100 (which hardly seems to serve any useful pupose anyway) but if you want to absolutely prevent it, you can feed the entire pipeline to | grep . which will report success if there was any output. (Or you could run xargs on a wrapper which always returns success if the exit code from grep is either 0 or 1, but that is more complex, and you will then see "success" even in the case of zero matches.)

like image 160
tripleee Avatar answered Sep 27 '22 18:09

tripleee