有没有一种方法可以将多个参数传递find -exec
给bash -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 -c
from-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
代替您的下划线(即代替上述命令中的“占位符”),并从$0
shell 命令内部访问它。
对于更普遍的问题是,当您将所有找到的文件传递给 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 {} +