查找:-exec缺少参数


206

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

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

外壳返回

find: missing argument to `-exec'

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

我对此表示感谢。

Answers:


340

-exec命令需要与被终止;(因此通常需要输入\;';'由外壳避免解译)或+。区别在于,with ;,每个文件调用一次命令,with +,调用所有文件名的次数尽可能少(通常一次,但是命令行有最大长度,因此可能会被拆分)。 。请参阅以下示例:

$ 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命令中添加{},否则在使用特殊字符时会产生问题。相反,您可以在之后将其他参数传递给shell -c command_string(请参阅参考资料man sh):

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

您将$在第一个示例中看到事物是由外壳评估的。想象有一个名为$(rm -rf /):-) 的文件

(附带说明:-不需要,但是命令后的第一个变量分配给了变量$0,这是一个特殊变量,通常包含正在运行的程序的名称,并将其设置为参数有点不干净,尽管它赢得了可能不会在这里造成任何伤害,因此我们将其设置为just,-然后从开始$1。)

所以你的命令可能像

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

但是有更好的方法。找到支撑andor,所以你可以做的东西一样find -name foo -or -name bar。但这也适用于-exec,如果命令成功退出,则结果为true,否则为false。请参阅以下示例:

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

它仅在命令成功执行的情况下运行打印,但命令不是成功truefalse

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


3
关键似乎是玛丽安(Marian)所说的“ ;;它本身是一个arg”。谢谢。
pjammer 2014年

3
那是关于我在-exec上阅读过的最好的描述。它非常强大,但是我总是很难找到正确的语法。这使一些事情变得更加清楚。特别是将命令包装在单独的外壳中。真好 谢谢。
Eurospoofer,2016年

3
请注意,-and并且-or不是可移植的。POSIX指定-a-o,并且实际上-a总是假定的(因此不需要)。
gniourf_gniourf

终止符之前也必须有一个空格。前"\;"不起作用,但" \;"可以起作用
frmdstryr

56

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

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

不确定是否会删除该文件的变量?有人知道是这样吗?
Abs

7
要测试这些东西,只需echo在命令之前添加一个,然后查看它的作用。
玛丽安·2010年

2
@Marian,echo是相当不可靠的-你不能告诉之间的区别echo "one argument"echo one argument(后者的输出是假的,因为它实际上是通过echo两个完全独立的参数)。最好执行像这样的操作-exec bash -c 'printf "%q " "$@"' _ ffmpeg -i {} -sameq {}.mp3 \; -printf '\n',它将以使无法打印的字符可见的方式打印输出,以便您可以检测DOS换行符和其他异常。
查尔斯·达菲

52

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

作品:

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

不起作用:

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

1
这经常使我绊倒。这些天之一,我将默认添加一个空格。
harperville

对我来说,它在Windows 7下的Cygwin中正好相反:有效,有空间-不能。但是,如果我删除\,则在前面加上空格;它有效,并且之前没有空间;并非如此,只是这里描述的方式。
WebComer '17

7

仅供参考:
我刚刚尝试在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 {}\;给出了相同的结果。:(
柯比

我正在运行Windows版Git附带的Bash shell,Dustin Cowles的答案对我有用。换句话说:没有引号,反斜杠由分号转义,后跟空格{}
mamacdon

含义没有区别,但是在某些情况下,您需要添加反斜杠,在某些情况下,您不能放反斜杠,在其他情况下,您可能会选择。
多米尼克

2

万一有人在Amazon Opsworks Chef bash脚本中看到类似的“ missing -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

2

另外,如果其他任何人都有“ -exec的find:缺少参数”,这可能会有所帮助:

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

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

2
这里;没有被引用或转义的意思是它可以被外壳使用,不能被读取find。另外,-f- f是两个不同的东西。
Charles Duffy

1

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

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

0

{}和&&都会由于命令行扩展而引起问题。我建议尝试:

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

如果exec中的第一个命令成功执行,而exec中的第二个命令执行了,它是否仍然可以访问 {}变量以删除正确的文件?
Abs

{}将扩展到什么?除非它包含两个点或逗号,否则将保持原样。
玛丽安(Marian)2010年

0

您必须在{}和之间放置一个空格\;

因此,命令将类似于:

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

-4

如果仍然出现“查找:-exec缺少参数”的情况,请尝试将execute参数用引号引起来。

find <file path> -type f -exec "chmod 664 {} \;"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.