Bash

如何將多個參數從find -exec傳遞給bash -c子shell?

  • March 1, 2022

有沒有辦法將多個參數從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 -cfrom-exec子句?

你不能在if 你使用;*之後加上參數。*檢查規格{}``+

-exec … 只有緊跟在僅包含兩個字元“{}”的參數之後的加號才能標點主表達式的結尾。加號的其他用途不應視為特殊。

此外,您將多個 args 傳遞給 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 命令內部訪問它。


find ... -exec對於更一般的問題,當您將所有找到的文件傳遞給 shell 命令並希望在循環中處理它們時,如何將額外的參數傳遞給嵌入在命令中的 shell 命令,可以這樣做:

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 {} +

引用自:https://unix.stackexchange.com/questions/692584