使用「find ... -exec sh -c '...' sh {} +」的 find 指令如何運作?

使用「find ... -exec sh -c '...' sh {} +」的 find 指令如何運作?

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

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

這裡究竟發生了什麼事?最後一個具體是sh {}做什麼的呢?看起來它只是為了安撫 find 的-exec命令,以便它有事情可做,一個 NOOP。

我可以很容易地放在echo {}那裡,它看起來工作得很好。

答案1

語法是:

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..."$@"這 3 個參數的列表也是如此:a、b 和 c。所以在:

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

為了內嵌腳本$0(例如在顯示錯誤訊息時使用)設為 ,find-sh並且"$@"是檔案清單(find擴展{}為的內容)。

透過使用execshell 的特殊內建函數:

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

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

相關內容