我正在查找包含“AAA”和“BBB”的目錄中的所有檔案。然后我想對每個找到的檔案進行修改/處理。檔案名確實包含空格。
grep
管道grep
似乎很簡單,但需要xargs
正確運行。
grep
(據我所知)中的多重匹配功能僅適用于“AAA”或“BBB”。
我所擁有的是:
for FILENAME in "$(grep -ilrZ "AAA" ./files/* | xargs -0 grep -ilr "BBB")"
do
echo "$FILENAME"
echo "match"
done
但是,這會將串列視為檔案(包括換行符)作為單個物體(即“匹配”只會列印一次)。
從for
子外殼中洗掉雙引號意味著每個空格都是要回圈的新事物,這會破壞檔案名。
uj5u.com熱心網友回復:
您grep -Z
在第一次呼叫中的使用也是第二種情況下問題的解決方案。
grep -ilrZ "AAA" ./files/* |
xargs -r0 grep -Zil "BBB" |
xargs -r0 -i echo "{} match"
-r
在第二個中使用grep
沒有意義,因為您只想精確檢查第一個輸出中的檔案grep
。
如果您只想列出檔案,當然,grep -l
已經這樣做了;大概,你會想要在第二個中做一些更復雜的事情xargs
。
另一種解決方案可能是
find ./files -type f \
-exec grep -qi "AAA" {} \; \
-exec grep -qi "BBB" {} \; \
-exec sh -c 'for f; do echo "$f matced"; done' _ {}
其作業方式是,如果-exec
失敗,則失敗的檔案將被 視為失敗的謂詞find
,因此將跳過其余的謂詞。到達最終謂詞的檔案將從所有先前的謂詞回傳成功。
grep -Z
后者應該在缺少 GNU 擴展等的非 Linux 平臺上作業xargs -0
。
如果它不明顯,find
也grep -r
檢查子目錄。如果您只想檢查當前目錄,-r
則從第一個目錄中省略grep
應該可以。對于find
,您可以添加-maxdepth 1
before-type f
以僅檢查當前目錄。
演示:https ://ideone.com/ELqKxZ
有關此主題的更多資訊,另請參閱https://mywiki.wooledge.org/BashFAQ/020和https://mywiki.wooledge.org/DontReadLinesWithFor
uj5u.com熱心網友回復:
@tripleee 有一個出色而可靠的答案。另一種選擇。假設你的 shell 是 bash 而你的 awk 是 GNU awk
shopt -s globstar # enable recursive globbing with **
gawk '
BEGINFILE {a = b = 0}
/AAA/ {a = 1}
/BBB/ {b = 1}
a && b {print FILENAME; nextfile}
' ./files/** 2>/dev/null
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/470668.html