我正在嘗試運行以下命令:
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 find
POSIX 相容的功能)。
如果您想堅持使用較舊的 GNU 查找,您可以使用-print0
withxargs -0
來獲得類似的功能:分組命令執行、支援任意檔名。
find a/folder b/folder -name '*.c' -o -name '*.h' -print0 | xargs -0 grep -I foobar /dev/null
始終在命令列上引用通配符find
。否則,如果您碰巧從包含檔案的目錄執行此命令.c
,則未加引號的內容將擴展到目前目錄中的檔案*.c
清單。.c
添加/dev/null
到grep
命令列是確保 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
當您想要將文件視為一個組時,它有一些限制,因為每個文件都是串行評估的,但您可以將輸出通過管道傳輸到其他地方就可以了