題 如何使用“find”忽略某些文件名?


我最喜歡的BASH命令之一是:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

它搜索指定SearchString的當前目錄下和之下的所有文件的內容。作為開發人員,這有時會派上用場。

但是,由於我當前的項目以及我的代碼庫的結構,我想通過不搜索包含“.svn”的目錄中或下面的任何文件或任何文件來使這個BASH命令更加高級。用“.html”結束

雖然找到了一些混淆我的MAN頁面。我嘗試使用-prune,它給了我奇怪的行為。為了嘗試僅跳過.html頁面(開始),我試過:

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

並沒有得到我希望的行為。我想我可能會忽略-prune的觀點。你能幫助我嗎?

謝謝


112
2018-03-05 23:28


起源


只是fyi: find 不是內置bash命令,而是一個單獨的程序 - WakiMiko
您可以使用搜索文件內部 grep -rl 'SearchString' - emanuele
@emanuele您好,歡迎來到SuperUser(以及Stack Exchange網絡)。這是我提出的一個問題,並且在2年半前得到了回答。通常情況下,如果您想添加問題的答案,請滾動到底部並在那裡回答,而不是在評論中。由於這個問題已經有了一個可接受的答案(帶有綠色複選標記的答案),因此你的答案不太可能得到很多關注。僅供參考。 - Cody S
嗨,這不是你問題的答案。這只是一個提示,正如你在序言中所說的那樣使用 find 在文件內搜索。 - emanuele
FWIW, -name '*.*' 找不到 所有 文件:只有那些 . 在他們的名下(使用 *.* 通常是DOS-ism,而在Unix中,通常只使用 * 為了那個原因)。要真正匹配它們,只需完全刪除參數: find . -exec ...。或者,如果您只想將grep應用於文件(並跳過目錄),那麼就這樣做 find . -type f -exec ...。 - Stefan


答案:


您可以使用find的negate(!)功能來匹配具有特定名稱的文件:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

因此,如果名稱以.html結尾或在路徑中的任何位置包含.svn,則它將不匹配,因此exec將不會被執行。


159
2018-03-06 00:40



我還應該指定-name'嗎。“在那裡的某個地方?我會在之前或在否定之後這樣做嗎? - Cody S
是你的意圖 *.* 匹配以確保它只匹配包含a的文件 .?如果沒有,則查找將匹配所有文件 name 指令,所以上面將匹配除html和svn之外的所有內容 - Paul
我想你想要的 -wholename '*.svn*' 而不是 -name。 - fuenfundachtzig
是的,它確實如此 .svn 目錄從搜索結果中排除。 - fuenfundachtzig
@本體 ! -name '.' 應該排除 . 從查找結果。 - Paul


我長期以來遇到過同樣的問題,有幾種解決方案適用於不同的情況:

  • ack-grep 是一種“開發者” grep“ 哪一個 默認情況下 跳過版本控制目錄和臨時文件。該 man 頁面說明瞭如何僅搜索特定文件類型以及如何搜索 定義你自己的
  • grep是自己的 --exclude 和 --exclude-dir 可以非常輕鬆地使用選項來跳過文件 水珠 和  目錄(不幸的是沒有目錄的通配)。
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... 應該工作,但從長遠來看,上述選項可能不那麼麻煩。

9
2018-03-06 13:54





下列 find 命令會修剪其名稱的目錄 包含  .svn,雖然它沒有下降到目錄中,但是已修剪的路徑名稱被打印...(-name '*.svn' 是原因!)..

您可以通過以下方式過濾掉目錄名稱: grep -d skip 它默默地跳過這樣的輸入“目錄名稱”。

使用GNU grep,您可以使用 -H 代替 /dev/null。 作為一個小問題: \+ 可以快得多 \;,例如。用於100萬個單行文件,使用 \; 花了 4m20s,使用 \+ 它只花了 1.2S

以下方法使用 xargs 代替 -exec,並假設沒有換行符 \n 在你的任何文件中 。這裡使用的, xargs 和find一樣 \+

xargs 可以通過將輸入分隔符更改為來傳遞包含連續空格的文件名 '\n' 隨著 -d 選項。

這將排除名稱的目錄 包含  .svn 和greps只有不以...結尾的文件 .html

find . \( -name '*.svn*' -prune  -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'

7
2018-03-06 03:29



謝謝你指出了 \+ -exec動作的變體。萬歲有輕微的問題! - Christian Long
當然,自從 + 不是shell的特殊字符,您不需要鍵入 \ 在它之前。 - Scott