尋找:-exec 缺少參數

尋找:-exec 缺少參數

我正在嘗試運行以下命令:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' +

這是回傳一個錯誤:

find: missing argument to -exec

我看不出這個命令有什麼問題,因為它似乎與手冊頁相符:

-執行指令{} +

-exec 選項的這個變體在選定的檔案上執行指定的命令,但命令列是透過在末尾附加每個選定的檔案名稱來建構的;該命令的調用總數將遠小於匹配檔案的數量。命令列的建構方式與 xargs 建構其命令列的方式大致相同。命令中只允許出現一個「{}」實例。該指令在起始目錄中執行。

我也嘗試過:

find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' {} +
find a/folder b/folder -name *.c -o -name *.h -exec 'grep -I foobar' '{}' +
find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar '{}' +
find a/folder b/folder \( -name *.c -o -name *.h \) -exec grep -I foobar '{}' +
find a/folder b/folder -name *.c -o -name *.h -exec grep -I foobar '{}' \+

答案1

您的嘗試存在幾個問題,包括使用反引號而不是引號(在問題的後續編輯中刪除)、在需要的地方缺少引號、在無用的地方額外引號、缺少分組子句的括號-o以及find使用的不同實現(詳情請參閱評論和聊天)。

無論如何,命令可以像這樣簡化:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} +

或者,如果您使用古老的 GNU find 版本,這應該始終有效:

find a/folder b/folder -name "*.[ch]" -exec grep -I foobar {} \;

答案2

「missing argument to -exec」通常表示 - 的參數exec缺少其終止符。終止符必須是僅包含字元的參數;(需要在 shell 命令中引用,因此通常寫為\;';'),或是兩個包含{}和 的連續參數+

斯蒂芬·查澤拉斯 (Stephane Chazelas) 已確定您正在使用舊版的 GNU find,它不支援-exec … {} +, 僅-exec {} \;.儘管 GNU 是 的較晚採用者-exec … {} +,但我確實建議您獲得一個不太古董的工具套件(例如西格溫,其中包括 git 和更多內容,或者GNUwin32,它缺少 git,但沒有 Cygwin 提供的壞員工試圖使用 linux-but-we-impose-windows 氛圍)。該功能是在 9 年前的 4.2.12 版本中添加的(這是最後一個確定的使 GNU findPOSIX 相容的功能)。

如果您想堅持使用較舊的 GNU 查找,您可以使用-print0withxargs -0來獲得類似的功能:分組命令執行、支援任意檔名。

find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null

始終在命令列上引用通配符find。否則,如果您碰巧從包含檔案的目錄執行此命令.c,則未加引號的內容將擴展到目前目錄中的檔案*.c清單。.c

添加/dev/nullgrep命令列是確保 grep 始終打印文件名的技巧,即使find碰巧找到單個匹配項也是如此。對於 GNU find,另一種方法是傳遞選項-H

答案3

如果一個命令如

find a/folder b/folder -name "*.c" -o -name "*.h" -exec grep -I foobar {} +

回傳錯誤

find: missing argument to -exec

可能的原因是 GNU 太舊find,不支援語法-exec mycommand {} +。在這種情況下,低效能替換是運行-exec mycommand {} \;,它將mycommand為每個找到的目標運行一次,而不是收集多個目標並mycommand僅運行一次。

然而,GNUfind不支援例如

find . -type f -and -name "*.ttf" -exec cp {} ~/.fonts +

因為 GNUfind僅支援文字組合{} +而不是更通用的{} additional parameters +。請注意,大括號和字元之間不能有任何內容+。如果你嘗試這樣做,你會得到同樣的錯誤:

find: missing argument to -exec

解決方法是使用{} additional parameters \;確實有效但會為每個找到的目標執行一次命令的語法。如果您需要 GNU 的更高效能,find則必須編寫一個包裝器腳本,該腳本可以將其他參數附加到給定的參數中。就像是

#!/bin/bash
exec mycommand "$@" additional parameters

應該夠好了。或者,如果您不想建立臨時文件,可以使用單行命令更改參數順序,如下所示:

find . -type f -and -name "*.ttf" -exec bash -c 'mycommand "$@" extra arguments' {} +

這將執行mycommand {list of ttf files} extra arguments.請注意,您可能需要在標誌後面對 bash 的特殊字元進行雙重轉義-c

答案4

過去我曾對 exec 語法感到頭痛。現在大多數時候我更喜歡更好的 bash 語法:

for f in `find a/folder b/folder -name "*.[ch]"`; do grep -I foobar $f; done

當您想要將文件視為一個組時,它有一些限制,因為每個文件都是串行評估的,但您可以將輸出通過管道傳輸到其他地方就可以了

相關內容