【问题标题】:find: missing argument to -exec查找:-exec 缺少参数
【发布时间】:2011-02-27 01:09:00
【问题描述】:

我今天得到了一个命令的帮助,但它似乎不起作用。这是命令:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;

外壳返回

find: missing argument to `-exec'

我基本上想要做的是递归地遍历一个目录(如果它有其他目录)并在.rm文件类型上运行ffmpeg命令并将它们转换为.mp3文件类型。完成后,删除刚刚转换的.rm 文件。

感谢您对此提供的任何帮助。

【问题讨论】:

    标签: bash shell find arguments exec


    【解决方案1】:

    我认为你需要做一些转义。

    find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} \-sameq {}.mp3 \&\& rm {}\;
    

    【讨论】:

      【解决方案2】:

      我现在想通了。当您需要在 exec 中运行两个命令时,您实际上需要有两个单独的 exec。这终于对我有用了。

      find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;
      

      【讨论】:

      • 不确定是否会获取要删除的文件的变量?有人知道是不是这样吗?
      • 要测试这些东西,只需在命令前添加echo 看看它的作用。
      • @Marian, echo 非常不可靠——你无法分辨echo "one argument"echo one argument 之间的区别(后者的输出为假,因为它实际上完全通过了echo 两个单独的论点)。最好执行-exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n' 之类的操作,它将以一种使不可打印字符可见的方式打印输出,以便您可以检测 DOS 换行符和其他奇怪的东西。
      【解决方案3】:

      {} 和 && 都会因为被命令行展开而出现问题。我建议尝试:

      find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;
      

      【讨论】:

      • 如果exec中的第一个命令成功,exec中的第二个命令被执行,它是否仍然可以访问{}变量来删除正确的文件?
      • 你认为{} 扩展成什么?除非它包含两个将保持原样的点或逗号。
      【解决方案4】:

      -exec 命令必须以; 终止(因此您通常需要键入\;';' 以避免被shell 解释)或+。不同之处在于;,每个文件调用一次命令,+,它被调用的次数尽可能少(通常是一次,但命令行有最大长度,所以它可能是拆分)与所有文件名。看这个例子:

      $ cat /tmp/echoargs
      #!/bin/sh
      echo $1 - $2 - $3
      $ find /tmp/foo -exec /tmp/echoargs {} \;
      /tmp/foo - -
      /tmp/foo/one - -
      /tmp/foo/two - -
      $ find /tmp/foo -exec /tmp/echoargs {} +
      /tmp/foo - /tmp/foo/one - /tmp/foo/two
      

      您的命令有两个错误:

      首先,您使用{};,但; 必须是它自己的参数。

      其次,命令结束于&&。您指定了“运行查找,如果成功,则删除名为 {};. 的文件。”。如果你想在-exec 命令中使用shell 的东西,你需要在shell 中显式运行它,比如-exec sh -c 'ffmpeg ... && rm'

      但是你不应该在 bash 命令中添加 {},当有特殊字符时会产生问题。相反,您可以在-c command_string 之后将其他参数传递给shell(请参阅man sh):

      $ ls
      $(echo damn.)
      $ find * -exec sh -c 'echo "{}"' \;
      damn.
      $ find * -exec sh -c 'echo "$1"' - {} \;
      $(echo damn.)
      

      您看到$ 在第一个示例中由shell 评估。想象一下有一个名为$(rm -rf /) 的文件:-)

      (旁注:- 不是必需的,但命令后的第一个变量分配给变量$0,这是一个特殊变量,通常包含正在运行的程序的名称并将其设置为参数有点不干净,虽然在这里可能不会造成任何伤害,所以我们将其设置为 - 并以 $1 开头。)

      所以你的命令可能是这样的

      find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
      

      但是有更好的方法。 find支持andor,所以你可以做find -name foo -or -name bar之类的东西。但这也适用于-exec,如果命令成功退出,则计算结果为 true,否则返回 false。看这个例子:

      $ ls
      false  true
      $ find * -exec {} \; -and -print
      true
      

      它仅在命令成功时才运行打印,它对true 执行此操作,但对false 执行此操作。

      因此,您可以使用两个与-and 链接的 exec 语句,并且只有在前者运行成功时才会执行后者。

      【讨论】:

      • 关键似乎是 Marian 的“the ; is an arg on it's own”的行,这对我来说是这样做的,灯泡明智和我的代码示例。谢谢。
      • 这是我在 -exec 上读到的最好的描述。它非常强大,但我总是发现很难为它找到正确的语法。这让一些事情变得更加清晰。特别是将命令包装在单独的外壳中。好的。谢谢。
      • 请注意 -and-or 不可移植。 POSIX specifies -a and -o,事实上-a 总是被假定的(因此不需要)。
      • 在终止符前也必须有一个空格。例如 "\;" 不起作用,但 " \;" 起作用
      • 为了将来遇到 ssh 错误的读者的利益,在 -exec 解决问题后将终止的转义分号括起来(Ubuntu 18.04.2 LTS): $ ssh remuser@remhost find Documents -执行回声 {} '\;'
      【解决方案5】:

      尝试在每个 \ 之前放置一个空格;

      作品:

      find . -name "*.log" -exec echo {} \;
      

      不起作用:

      find . -name "*.log" -exec echo {}\;
      

      【讨论】:

      • 这经常让我绊倒。这几天,我会默认添加一个空格。
      • 对我来说,它在 Windows 7 下的 Cygwin 中正好相反:之前没有空格\;有效,有空间 - 不。但是如果我删除\,前面有空格;它可以工作,并且之前没有空格;它没有,就像这里描述的那样。
      【解决方案6】:

      仅供参考:
      我刚刚尝试在 Cygwin 系统(在 Windows 上模拟 UNIX)上使用“find -exec”命令,似乎必须删除分号前的反斜杠:
      find ./ -name "blabla" -exec wc -l {} ;

      【讨论】:

      • 我真的很困惑。 find /etc/nginx -name '*.conf' -exec echo {} ;find /etc/nginx -name '*.conf' -exec echo {}\; 给出了相同的结果。 :(
      • 我正在运行 Git for Windows 附带的 Bash shell,Dustin Cowles 的回答对我有用。换句话说:没有引号,反斜杠用分号转义,{} 后面有空格。
      • 意思上没有区别,但是有些情况下需要放反斜杠,有些情况下不能放反斜杠,再有其他情况下可以选择。
      【解决方案7】:

      以防万一有人在 Amazon Opsworks Chef bash 脚本中看到类似的“缺少 -exec args”,我需要添加另一个反斜杠来转义 \;

      bash 'remove_wars' do
        user 'ubuntu'
        cwd '/'
        code <<-EOH
          find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
        EOH
        ignore_failure true
      end
      

      【讨论】:

        【解决方案8】:

        另外,如果其他人有“find:missing argument to -exec”这可能会有所帮助:

        在某些 shell 中,您不需要进行转义,即您不需要“;”前面的“\”。

        find <file path> -name "myFile.*" -exec rm - f {} ;
        

        【讨论】:

        • ; 在这里没有被引用或转义意味着它可以被 shell 使用,不能被find 读取。另外,-f- f 是两个不同的东西。
        【解决方案9】:

        如果您仍然收到“查找:缺少 -exec 的参数”,请尝试将执行参数用引号括起来。

        find <file path> -type f -exec "chmod 664 {} \;"
        

        【讨论】:

        • find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified ‘... {} ...’
        【解决方案10】:

        你必须在{}\;之间加一个空格

        所以命令会是这样的:

        find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {} \;
        

        【讨论】:

          【解决方案11】:

          对于其他在使用 GNU 时遇到问题的人,请在 Windows 命令提示符下查找二进制文件。分号需要用^转义

          find.exe . -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 ^;
          

          【讨论】:

          • 非常感谢,这正是我的问题。
          猜你喜欢
          • 2014-04-05
          • 1970-01-01
          • 1970-01-01
          • 2012-01-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-22
          • 2017-12-16
          相关资源
          最近更新 更多