Shell-Script

在 find -exec 呼叫中執行使用者定義的函式

  • February 28, 2022

我在 Solaris 10 上,我用 ksh (88)、bash (3.00) 和 zsh (4.2.1) 測試了以下內容。

以下程式碼不會產生任何結果:

function foo {
   echo "Hello World"
}

find somedir -exec foo \;

find 確實匹配了幾個文件(如用 替換所示-exec ...-print,並且在從呼叫外部呼叫時,該函式可以正常工作find

以下是該man find頁面的內容-exec

-exec command 如果執行的命令返回一個
零值作為退出狀態。結尾
命令必須用轉義符打斷
分號 (;)。命令參數 {} 是
替換為目前路徑名。如果
-exec 的最後一個參數是 {} 而你
指定 + 而不是分號 (;),
該命令被呼叫的次數更少,與
{} 替換為路徑名組。如果
該命令的任何呼叫都會返回一個
非零值作為退出狀態,找到
返回非零退出狀態。

我可能會做這樣的事情:

for f in $(find somedir); do
   foo
done

但我害怕處理欄位分隔符問題。

是否可以從呼叫中呼叫 shell 函式(在同一個腳本中定義,讓我們不要為範圍問題而煩惱)find ... -exec ...

我嘗試了兩者/usr/bin/find/bin/find得到了相同的結果。

Afunction對 shell 來說是本地的,因此您需要find -exec生成一個 shell 並在該 shell 中定義該函式,然後才能使用它。就像是:

find ... -exec ksh -c '
 function foo {
   echo blan: "$@"
 }
 foo "$@"' ksh {} +

bash允許通過環境導出函式export -f,因此您可以(在 bash 中):

foo() { ...; }
export -f foo
find ... -exec bash -c 'foo "$@"' bash {} +

ksh88必須typeset -fx導出功能(不是通過環境),但只能由 執行的 she-bang less 腳本使用ksh,所以不能使用ksh -c.

另一種選擇是:

find ... -exec ksh -c "
 $(typeset -f foo)"'
 foo "$@"' ksh {} +

也就是說,用於typeset -f轉儲foo內聯腳本中的函式定義。請注意,如果foo使用其他功能,您還需要轉儲它們。

ps -f或者,您可以通過環境變數傳遞它,而不是在命令行上傳遞函式定義(例如在輸出中可見):

FUNCDEFS=$(typeset -f foo) find ... -exec ksh -c '
 eval "$FUNCDEFS" &&
   unset -v FUNCDEFS &&
   foo "$@"' ksh {} +

unset -v FUNCDEFS避免污染由該foo函式啟動的命令的環境(如果有))。

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