Shell-Script

這個使用“find … -exec sh -c ‘…’ sh {} +”的查找命令如何工作?

  • March 21, 2022

@StephaneChazelas 對此問答發布了以下解決方案:使用“find -exec {} +”時遇到一些問題

$ find . -iname "*.extension" -exec sh -c '
 exec <command> "$@" <additional parameters>' sh {} +

這裡到底發生了什麼?最後一個具體是sh {}做什麼的?似乎它只是為了安撫 find 的-exec命令,以便它有事可做,一個 NOOP。

我可以很容易地把它放在echo {}那裡,它似乎工作得很好。

語法是:

find ... -exec cmd {} +

find將根據其中的條件找到許多文件,...cmd以該文件路徑列表作為參數執行,在不超過命令參數大小限制的情況下盡可能多地執行。

如果需要,它可能會拆分文件列表並cmd多次呼叫。例如,它最終可能會呼叫:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

一個限制是它{}必須是最後的。例如,您不能寫:

find ... -exec cmd {} other args +

就像你可以用';'而不是'+'.

你可以寫:

find ... -exec echo foo {} +

但不是:

find ... -exec echo {} foo +

因此,如果您確實需要在cmd文件列表之後添加一些額外的參數,則必須求助於呼叫 shell。(您需要呼叫 shell 的其他原因是任何時候需要使用 shell 功能,如重定向、管道、一些字元串擴展……)

sh -c 'inline-script' x a b c, 對於inline-script, $0is x, $1is a, $2is b"$@"這三個參數的列表也是如此:a、b 和 c。所以在:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

對於內聯腳本$0(例如在顯示錯誤消息時使用)設置為find-sh並且"$@"是文件列表(find擴展{}為)。

通過使用 shell 的exec特殊內置函式:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

我們告訴 shell 不要派生一個額外的程序來執行cmd,而是在同一個程序中執行它(用該命令替換正在執行的 shell 程序)。一些 shellzsh和一些實現ksh隱式地為內聯腳本中的最後一個命令執行此操作(bash當內聯腳本中只有一個命令時,如這裡)。

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