【问题标题】:Too many arguments in findfind 中的参数太多
【发布时间】:2014-04-06 20:07:42
【问题描述】:
#!/bin/bash

read DIR
read SEARCH

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

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

【问题讨论】:

  • 您的DIRSEARCH 的值可能让find 感到惊讶。
  • 看看@Bex 的评论,也许你可以在if 之前显示echoing DIRSEARCH 的结果?
  • 推荐你引用$DIR$SEARCH来保护空白,例如:find "$DIR" -type f...
  • 不要这样使用 [。就做if find ... | grep -q .; then
  • 您想打印find 的结果还是仅仅打印它找到了匹配项?对于第二种情况,您应该添加一个 -quit 选项来查找,以便它终止而无需进一步查看。

标签: bash


【解决方案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之前的重定向操作符。

【讨论】:

    【解决方案2】:

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

    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 toxargs. This will give thegrep -q` 声明你正在传递的文件。

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

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

    【讨论】:

    • +1 建议不使用[ ... ] 并使用xargs 让整体命令反映grep 的结果; find-print0GNU grep--null 不符合 POSIX 标准,但如果您使用 -0 而不是 --null,它也可以在 FreeBSD/OSX 上运行;也就是说:如果你用+而不是\;终止-exec,似乎grep的退出代码已经通过,所以不需要xargs;另外:请参阅我的答案以获得纯 grep(也不符合 POSIX)替代方案。
    【解决方案3】:

    一般

    • 始终双引号变量引用以保护它们免受分词和其他 shell 扩展。

    • 要根据命令的退出代码创建条件,您不需要[...][[ ... ]],只需按原样使用命令即可。

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

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

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


    特别是

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

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

    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
    

    【讨论】:

      【解决方案4】:

      当你运行时:

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

      find/grep 的标准输出被拆分为单词,每个单词成为 [ 命令的参数。 [ or test 命令的 POSIX 版本对于它应该接受什么有严格的想法,并且您的命令的输出几乎不可避免地与这些想法不匹配,因此您会收到“参数过多”错误消息。

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

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

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

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          比原始问题更能说明您的问题的答案(因为其他答案确实解决了您问题中的问题)。

          您似乎想提示用户输入要搜索的目录和要在目录中的文件中查找的模式。为此,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
          

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


          1最好先说明您的问题 X,然后再展示您尝试的内容(即 Y),这样我们就可以清楚地了解您想要实现的目标和你是如何尝试实现它的。这是关于提问的一般性建议!

          【讨论】:

            猜你喜欢
            • 2015-04-27
            • 2018-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-02-06
            • 1970-01-01
            相关资源
            最近更新 更多