Bash

grep 模式 A 的文件,但排除模式 B 的文件

  • June 9, 2019

我想 grep 包含模式 A (iwant) 的文件,但我想排除包含模式 B (idontwant) 的文件。

例子:

read -p "...what are you looking for: " iwant
read -p "...what should not be included: " idontwant

iwant="blue car" 
idontwant="red car"

假設我有以下文件:

-rw-rw-r--.  1 terpentin terpentin  45 Jun  8 16:04 blue.car
-rw-rw-r--.  1 terpentin terpentin  44 Jun  8 16:05 mixed.car
-rw-rw-r--.  1 terpentin terpentin  40 Jun  8 16:04 red.car
find . -type f -print -exec cat {} \;

./mixed.car
blue car
red car
blue car

./red.car
red car
red car
red car

./blue.car
blue car
blue car
blue car

結果怎麼可能只得到文件“./blue.car”?

原始內容包括數百個長文本文件,這使得盡可能節省資源非常重要。

採用

find . -type f ! -exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -print

或者

find . -type f -exec grep -q "$iwant" {} ';' ! -exec grep -q "$idontwant" {} ';' -print
  • 命令中的術語(有時稱為“謂詞”)find 被表徵為測試(例如,  -type f)和動作(例如, -print和 -delete)。可能很難從手冊頁中找出-exec既是 action又是 test的內容。所以,就像
尋找 。-type f -mtime -30 -name '*.txt' -可讀 -size +5 *test 6*  *test 7*  *test 8* …

依次將搜尋範圍縮小到滿足所有條件(滿足所有指定測試)的文件,因此

尋找 。-exec *cmd 1* {} ';' -exec *cmd 2* {} ';' -exec *cmd 3* {} ';' …

查找所有命令都成功的文件。

  • 任何find測試都可以通過在它前面加上 來否定(反轉)!。因此find . ! -type d可以找到普通文件、符號連結、命名管道、套接字和設備文件——除了目錄之外的所有內容。
  • 請注意,! -exec grep …不等於-exec grep -v …-exec grep -v …將找到至少有一行不匹配的文件。  ! -exec grep …將找到沒有行匹配的文件。
  • -q選項 to是官方的grep同義詞--quiet,但它也意味著快速。它不寫入任何輸出(可能除了錯誤消息,如適用),但它也會在找到匹配項後立即退出——它不會將每個文件都讀到最後以找到每個匹配項。(當然,如果文件不包含任何匹配項,則grep必須完整讀取它才能確定。)
  • 所以(TL;DR)命令找到文件
grep -q "$iwant" *文件*

成功並且

grep -q "$idontwant"*文件*

失敗(因為我們在它前面加上!)。

  • 這兩個命令在功能上是等效的,但可能具有不同的性能(即,可能需要不同的執行時間)。如果只有少數文件包含搜尋字元串,
尋找 。-type f -exec grep -q "$iwant" {} ';' !-exec grep -q "$idontwant" {} ';' -列印

會更快,因為這grep "$iwant"會消除大部分文件。如果許多文件包含這兩個字元串,則

尋找 。-類型 f !-exec grep -q "$idontwant" {} ';' -exec grep -q "$iwant" {} ';' -列印

會更快,因為這! grep "$idontwant"會消除大部分文件。

引用自:https://unix.stackexchange.com/questions/523716