查找中的参数太多了

时间:2014-04-06 20:07:43

标签: bash

#!/bin/bash

read DIR
read SEARCH

if [ `find $DIR -type f -exec grep $SEARCH /dev/null {} \;` ]; then
    echo "Find"
fi

此代码有什么问题?我有一个错误:参数太多

6 个答案:

答案 0 :(得分:1)

[[[test不是if shell结构的一部分,而是提供用于进行比较的命令。

您可以尝试以下方式:

#!/bin/bash

read DIR
read SEARCH

[[ $(find "$DIR" -type f -exec grep "$SEARCH" {} \;) ]] && echo "Find"
# or
[[ -n $(find "$DIR" -type f -exec grep "$SEARCH" {} \;) ]] && echo "Find"
# or
[[ $(find "$DIR" -type f -exec grep "$SEARCH" {} \;) != "" ]] && echo "Find"

您也可以尝试:

if [[ $(find "$DIR" -type f -exec grep "$SEARCH" {} \;) ]]; then
    echo "Find"
fi

否则,不要忘记/ dev / null之前的重定向运算符。

答案 1 :(得分:1)

我会一起删除测试(即[ ... ]):

if find "$DIR" -type f -print0 | xargs --null grep -q "$SEARCH"
then
    echo "Find"
fi

find "$DIR" will execute and the results will be passed to xargs . This will give the grep -q`声明您传递的文件。

此语句的结果将是管道中 last 命令的退出状态,即grep。如果grep找到您要搜索的内容,则会返回退出代码0。否则,它将返回非零的退出代码。 if会选择此项,如果if返回零,则会执行语句的grep部分。

唯一的问题是,xargs可能会多次执行grep,您将获得最后grep的状态。但是,如果发生这种情况,那么使用$(...)无论如何都会失败。

答案 2 :(得分:1)

一般

  • 始终双引号变量引用,以防止它们进行分词和其他shell扩展。

  • 要根据命令的退出代码创建条件,您不需要[...][[ ... ]],只需使用命令AS IS。 < / p>

示例:要测试当前文件夹中的任何*.txt文件是否包含单词needle,您可以使用:

if grep -q "needle" *.txt; then # ...

注意:-q会抑制grep的输出;通常,使用重定向来抑制不需要的输出,例如&> /dev/null


<强>具体地

find的退出代码与-exec和终结符\;结合使用时,仅表示是否调用了find 本身成功,但不反映用-exec调用的命令的结果。因此,整体命令不会反映grep是否成功。

如果您想使用find请务必使用-exec而不是+ 终止\;命令 - 这显然可以确保调用的命令的退出代码通过(使用GNU find 4.4.2和OS X 10.9.2中的FreeBSD find版本验证)。对于+-exec的行为类似于xargs(默认情况下):使用所有匹配路径调用一次指定的命令(除非所有匹配的路径都不适合单个命令行。)

if find "$DIR" -type f -exec grep -q "$SEARCH" {} + ; then # note the `-q`, `+`
  echo "Found."
fi

但是,在具体的情况下,您可能只会grep本身一些 grep实现(例如,GNU grep(Linux)和FreeBSD grep(OSX))具有选项-r(别名: -R,以递归方式搜索指定的输入目录(使用--include <glob>--exclude <glob>按文件名模式进行过滤):

if grep -q -r "$SEARCH" "$DIR"; then
  echo "Found."
fi

答案 3 :(得分:1)

当你跑步时:

if [ `find $DIR -type f -exec grep $SEARCH /dev/null {} \;` ]; then

find / grep的标准输出被分成单词,每个单词成为[命令的参数。 [ or test命令的POSIX版本对于它应该接受的内容有严格的想法,并且命令的输出几乎不可避免地与这些想法相匹配,因此您得到了太多的参数&#39;错误信息。

我们并不完全清楚你想做什么,但是你已经被其他人给了很多想法。我最好的猜测是你需要:

if find "$DIR" -type f -exec grep "$SEARCH" /dev/null {} +
then echo "Found"
else echo "Not found"
fi

请注意,我在"$DIR""$SEARCH"周围使用了双引号;这可以避免令人讨厌的惊喜。

您使用/dev/null来确保列出文件名也是我使用的技巧。

答案 4 :(得分:0)

尝试在设置find $DIR -type f -exec grep $SEARCH /dev/null {} \;DIR的情况下运行SEARCH并查看输出结果。可能它很长,命令行长度有一定的限制。既然您似乎只是检查输出是否为空,那么肯定有一种方法可以在不将整个字符串放在命令行上的情况下检查它 - 您可能只需要检查find的返回码,或者一个快速而肮脏的解决方案,计算字节并检查是否有大于零:

if  [ `find $DIR -type f -exec grep $SEARCH /dev/null {} \; | wc --bytes` -gt 0 ]; then
    echo "Find"
fi

答案 5 :(得分:0)

关于您的问题的答案比原始问题更多(因为其他答案确实解决了您问题中的问题)。

似乎您要提示用户搜索目录以及在目录中的文件中查找的模式。为此,find无用,因为grep可以在目录中递归搜索。

我真的不知道你最想做什么(也许你应该指定这个,以便we don't answer about Y when your original problem is X)。

假设您的问题是 1

  

如何向用户提示目录和模式,并确定是否在目录(和子目录)中包含的至少一个文件中找到此模式。我不想知道在哪个文件中找到模式,只知道它是否存在。

(我假设这是你的问题,因为这是你的代码似乎在你的OP中做的事情。)

要回答这个问题:

IFS= read -rp 'Enter a directory: ' dir
IFS= read -rp 'Enter a pattern: ' search
if grep -Rq -- "$search" "$dir"; then
    echo "Pattern found"
else
    echo "Pattern not found"
fi

顺便说一下,这比第一个找到的文件之后不使用find的任何其他-quit方法更有效,因为grep带有-q }选项将在找到第一个匹配后立即退出。


1 最好首先陈述你的问题X,然后展示你的尝试(即Y),以便我们清楚地了解你想要达到的目标和你是如何努力实现它的。这是我可以提出的关于提问的一般建议!