这是我的剧本
eval "find \\( -type f -a \\( -name '*.h' \\) \\) -print0" | xargs -0 -n100 grep -f <(echo "stdio")
echo $?
Run Code Online (Sandbox Code Playgroud)
找不到任何内容,退出代码为123。
如果我如下修改
echo "stdio" >.P
eval "find \\( -type f -a \\( -name '*.h' \\) \\) -print0" | xargs -0 -n100 grep <.P
echo $?
Run Code Online (Sandbox Code Playgroud)
找到了某些内容,但退出代码仍为123。
那怎么了?
================================================== ====================
实际上,我只想编写一个小脚本以使find + xargs + grep更容易。例如,
xgrep -e PATTERN1 -e PATTERN2 ... * .c * .h
将执行
find -name * .c -o -name * .h | xargs grep -f <(回显“ $ PATTEN1
$ PATTERN2”)
使用-f选项而不是-e是为了避免在模式中转义单引号或双引号时遇到麻烦。
#!/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")
Run Code Online (Sandbox Code Playgroud)
123表示“以非零状态退出的任何调用”。因此请至少xargs运行grep两次(因为您输入的文件太多,以至于它们超出了最大命令行长度(最多限制为100个文件)),并且至少有一次调用是在一组不包含任何匹配项的文件上进行的,从而导致退出代码从grep到非零(失败)。
也许您应该解释您要完成的工作。在eval看起来多余和双重定向可能不会完成你想要的东西(grep的标准输入不能同时从连接管eval和.P)。
如果您想参数化的第一个参数grep,则可以执行以下操作
#!/bin/sh
find -type f -name '*.h' -print0 |
xargs -0 -n100 grep "$1"
Run Code Online (Sandbox Code Playgroud)
...在其中以例如stdio第一个参数的形式调用它。
(还要注意简化了的参数find。您只有两个谓词,因此不需要在括号中加上任何内容,然后-a也可以将其删除。)
如果存在grep返回零匹配项的调用,则退出代码仍为123 。您可以通过省略来减少机会-n 100(无论如何它似乎几乎没有任何作用),但是如果您要绝对地防止它发生,则可以提供整个管道,| grep .如果有任何输出,它将报告成功。(或者,您可以xargs在包装器上运行,如果from的退出代码grep为0或1,则该包装器总是会返回成功,但这更加复杂,即使在零匹配的情况下,您也会看到“成功”。)