find:缺少-exec的参数

Abs*_*Abs 198 bash shell arguments exec find

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

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;
Run Code Online (Sandbox Code Playgroud)

shell返回

find: missing argument to `-exec'
Run Code Online (Sandbox Code Playgroud)

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

我很感激任何帮助.

Mar*_*ian 327

-exec命令需要与被终止;(因此通常需要键入\;';'以避免由外壳解译)或+.不同之处在于;,每个文件调用一次命令,其中+,所有文件名的调用次数尽可能少(通常为一次,但命令行有最大长度,因此可能会被拆分) .看这个例子:

$ 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
Run Code Online (Sandbox Code Playgroud)

您的命令有两个错误:

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

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

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

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

您可以$在第一个示例中看到shell对其进行评估.想象一下,有一个名为$(rm -rf /):-) 的文件

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

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

find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;
Run Code Online (Sandbox Code Playgroud)

但还有更好的方法.找到支撑andor,所以你可以做的东西一样find -name foo -or -name bar.但这也适用-exec,如果命令成功退出,则计算结果为true,否则计算结果为false.看这个例子:

$ ls
false  true
$ find * -exec {} \; -and -print
true
Run Code Online (Sandbox Code Playgroud)

如果命令成功,它只运行打印,它执行true但不适用false.

因此,您可以使用两个与a链接的exec语句-and,如果前者成功运行,它将只执行后者.

  • 关键似乎是玛丽安的"the; is a arg on the own",这就是为我做的,灯泡明智和我的代码样本.谢谢. (3认同)
  • 这是我在-exec上读到的最好的描述.它非常强大,但我总觉得很难为它获得正确的语法.这使得一些事情变得更加清晰.特别是将命令包装在单独的shell中.尼斯.谢谢. (3认同)
  • 请注意,`-and`和`-or`不可移植.[POSIX指定`-a`和`-o`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html),实际上`-a`总是被假设(因此不需要) . (3认同)

Abs*_*Abs 53

我现在明白了.当你需要在一个find中的exec中运行两个命令时,你需要实际拥有两个独立的exec.这最终对我有用.

find . -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 \; -exec rm {} \;
Run Code Online (Sandbox Code Playgroud)

  • 要测试这些东西,只需在命令之前添加一个`echo`,看看它的作用. (7认同)
  • @ Marian,`echo`非常不可靠-您无法分辨`echo“一个参数”`和“ echo一个参数”之间的区别(后者的输出为false,因为它实际上传递了“ echo`两个完全独立的参数” )。做类似`-exec bash -c'printf“%q”“ $ @”“ _ ffmpeg -i {} -sameq {} .mp3 \会更好。-printf'\ n'`,它将以使非打印字符可见的方式打印输出,以便您可以检测DOS换行符和其他异常。 (2认同)

Dus*_*les 49

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

作品:

find . -name "*.log" -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

不起作用:

find . -name "*.log" -exec echo {}\;
Run Code Online (Sandbox Code Playgroud)

  • 这经常让我绊倒。有一天,我会默认添加一个空格。 (3认同)

Dom*_*que 7

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


Aza*_*ssa 7

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

所以命令将是这样的:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {} \;
Run Code Online (Sandbox Code Playgroud)


laz*_*lev 6

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

find.exe . -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 ^;
Run Code Online (Sandbox Code Playgroud)