按內容遞迴查找文件

按內容遞迴查找文件

我想按內容在來源樹中遞歸查找文件。我使用 grep 嘗試了以下操作:

$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)

這會按我想要的方式返回每一行,但現在,我想獲取每個匹配文件的文件名,所以我將其更改為:

$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)

但我沒有列印檔名,而是只得到

(standard input)

列印到標準輸出。如何修復此問題以獲取每個文件名和路徑(以sed在其上使用)?

我想要做的:尋找每個printf包含以下行的文件%sbcm_errmsg(rv)然後將以下 sed 命令應用於找到的文件:

sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'

答案1

我認為你把事情過於複雜化了。要foo在目前目錄和子目錄中的所有檔案中尋找字串,只需執行

grep -r "foo" *

預設情況下,grep 輸出匹配行,前面加上找到它的檔名。

以下將僅輸出檔名,而不輸出匹配行:

grep -rl "foo" *

答案2

按照@steeldriver的最初想法,你可以這樣做:

egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'

答案3

grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
        /%s/!b
        /printf/!b
        /bcm_errstr(rv)/!b
        s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'

我們首先運行一個遞歸目錄。從目前目錄掃描具有以下字串的檔案: printf、%s 和 bcm_errstr(rv) 位於同一行,但可能以任意順序。grep幫助我們做到這一點的選項是:

  • -r=> 將遞歸啟動目前目錄及以下目錄中的所有檔案。
  • -l=> 將列出符合條件的檔案名,即所有 3 個字串位於同一行。
  • -Z=> 所選檔案名稱以空分隔(\0)而不是通常的換行符號(\n),以便我們能夠處理任何類型的檔案名稱。
  • -P=> 啟用 Perl 正規表示式引擎,從而我們能夠使用前瞻來確定 3 個字串是否存在於同一行中。

在管道的另一端,xargs正在等待接收檔案名,以 \0 分隔。然後,它盡可能地將所有這些檔案名稱提供給 sed 命令行。您已經從上一個問題中知道了 sed 命令,它在其中執行 subs。僅在同一行包含 3 個字串的那些行上。

相關內容