如何将多个参数从“find -exec”传递到“bash -c”子 shell?

如何将多个参数从“find -exec”传递到“bash -c”子 shell?

有没有一种方法可以将多个参数传递find -execbash -c子 shell?

给定这个工作调用,它搜索与 glob 模式(例如"*dogs.mp4)匹配的所有视频,然后ffmpeg在子 shell 中执行,并在文件已存在的情况下进行检查和警告:

find . -iname "*.mp4" -exec bash -c 'if [[ -f "${1%.*}_540.mp4" ]]; then echo "Already exists: $1"; else ffmpeg -i "$1" -vf "scale=540:-1" "${1%.*}_540.mp4" ; fi ;' _ {} +

为了避免540对我替换的大小进行硬编码$2,然后将大小作为参数传递到{}(to _ {} 540 +) 之后,以便命令变为:

find . -iname "*.mp4" -exec bash -c 'if [[ -f "${1%.*}_$2.mp4" ]]; then echo "Already exists: $1"; else ffmpeg -i "$1" -vf "scale=%2:-1" "${1%.*}_%2.mp4" ; fi ;' _ {} 540 +

上面的行抛出一个错误find: -exec: no terminating ";" or "+"::

我的理解是,这{}是文件名的占位符,并且{} +(或{} \;)必须位于命令末尾。

在这种情况下,如何将附加参数传递给bash -cfrom-exec子句?

答案1

你不能提出论据如果{}您正在使用+;查看规格

-exec ... 只有紧跟在仅包含两个字符“{}”的参数后面的加号才能标点主表达式的末尾。加号的其他用途不应被视为特殊用途。

另外,您将多个参数传递给 shell(使用 +),但仅使用$1这意味着您将忽略找到的其余文件。您需要在 shell 命令中放置一个循环。看https://unix.stackexchange.com/a/321753/135943举一些例子,但总的来说,它看起来像:

find dirname ... -exec sh -c 'for f do somecommandwith "$f"; done' placeholder {} +

无论如何,你都在“硬编码”大小。您也可以将其硬编码到实际的 shell 命令中;这比最后将其硬编码到参数列表中更容易。但如果你坚持的话,你可以通过540 代替您的下划线(即代替上述命令中的“占位符”),并从$0shell 命令内部访问它。


对于更普遍的问题是,当您将所有找到的文件传递给 shell 命令并想要在循环中处理它们时,如何将附加参数传递给嵌入在命令中的 shell 命令find ... -exec,可以这样做:

find dirname ... -exec sh -c 'arg1="$1"; arg2="$2"; shift 2; for f do somecommandwith "$f" "$arg1" "$arg2"; done' placeholder firstextraarg secondextraarg {} +

但真正的问题是,你为什么想这么做? 您可以更轻松地将“firstextraarg”和“secondextraarg”值直接放入 shell 命令中:

find dirname ... -exec sh -c 'for f do somecommandwith "$f" firstextraarg secondextraarg; done' placeholder {} +

相关内容