-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支持and和or,所以你可以做find -name foo -or -name bar之类的东西。但这也适用于-exec,如果命令成功退出,则计算结果为 true,否则返回 false。看这个例子:
$ ls
false true
$ find * -exec {} \; -and -print
true
它仅在命令成功时才运行打印,它对true 执行此操作,但对false 执行此操作。
因此,您可以使用两个与-and 链接的 exec 语句,并且只有在前者运行成功时才会执行后者。