Got exit code 123 in find + xargs grep

送分小仙女□ 提交于 2019-12-01 10:43:42

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.)

I'm posting this as a separate answer in response to your recent edit. I don't particularly want to change my existing answer, which already addresses the fundamental question.

Your script is unfortunately a classic example of the problem described in http://mywiki.wooledge.org/BashFAQ/050: "I am trying to put my command in a variable, but"...

The short version is "don't do that". The long version is, try to use arrays, and avoid variables where they are not absolutely necessary. Here is an attempt at refactoring your tool along those lines.

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

grep_patterns=( )
grep_options=( )

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

find_options=("${ARGV[@]:$i}")

find -type f -a \( "${find_options[@]}" \) -print0 |
xargs -0 grep "${grep_options[@]}" "${grep_patterns[@]}"

I'm not sure passing multiple -e options to grep is supported everywhere, but it works fine with GNU grep and simplifies things to my mind.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!