簡體   English   中英

使用 grep --exclude/--include 語法不通過某些文件進行 grep

[英]Use grep --exclude/--include syntax to not grep through certain files

我正在目錄樹中的文本文件中查找字符串foo= 它在一台普通的 Linux 機器上,我有 bash shell:

grep -ircl "foo=" *

目錄中還有許多與"foo="匹配的二進制文件。 由於這些結果不相關並且會減慢搜索速度,我希望 grep 跳過搜索這些文件(主要是 JPEG 和 PNG 圖像)。 我該怎么做?

我知道有--exclude=PATTERN--include=PATTERN選項,但是模式格式是什么? grep 的手冊頁說:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

搜索grep includegrep include excludegrep exclude和變體沒有找到任何相關內容

如果只有在某些文件中有更好的 grep 方法,我完全贊成; 移動有問題的文件不是一種選擇。 我不能只搜索某些目錄(目錄結構一團糟,到處都是)。 此外,我無法安裝任何東西,所以我必須使用常用工具(如grep或建議的find )。

使用 shell 通配語法

grep pattern -r --include=\*.cpp --include=\*.h rootdir

--exclude的語法是相同的。

請注意,星號用反斜杠轉義,以防止它被 shell 擴展(引用它,例如--include="*.cpp" ,也可以)。 否則,如果當前工作目錄中有與模式匹配的任何文件,命令行將擴展為類似grep pattern -r --include=foo.cpp --include=bar.cpp rootdir ,它只會搜索文件命名為foo.cppbar.cpp ,這很可能不是您想要的。

更新 2021-03-04

我已經編輯了原始答案以刪除括號擴展的使用,這是由 Bash 和 zsh 等多個 shell 提供的功能,用於簡化這樣的模式; 但請注意,大括號擴展不符合 POSIX shell。

原來的例子是:

grep pattern -r --include=\*.{cpp,h} rootdir

搜索根目錄rootdir中的所有.cpp.h文件。

如果您只想跳過二進制文件,我建議您查看-I (大寫 i)選項。 它忽略二進制文件。 我經常使用以下命令:

grep -rI --exclude-dir="\.svn" "pattern" *

它遞歸搜索,忽略二進制文件,並且不查看 Subversion 隱藏文件夾內部,無論我想要什么模式。 我在工作時在我的盒子上將它別名為“grepsvn”。

請看一下ack ,它正是為這些情況而設計的。 你的例子

grep -ircl --exclude=*.{png,jpg} "foo=" *

用 ack 完成

ack -icl "foo="

因為默認情況下 ack 從不查看二進制文件,並且默認情況下 -r 處於啟用狀態。 如果你只想要 CPP 和 H 文件,那么就做

ack -icl --cpp "foo="

grep 2.5.3 引入了--exclude-dir參數,它將以您想要的方式工作。

grep -rI --exclude-dir=\.svn PATTERN .

您還可以設置環境變量: GREP_OPTIONS="--exclude-dir=\\.svn"

不過我會支持安迪ack投票,這是最好的。

很長時間后我發現了這一點,您可以添加多個包含和排除,例如:

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js

建議的命令:

grep -Ir --exclude="*\.svn*" "pattern" *

在概念上是錯誤的,因為 --exclude 適用於 basename。 換句話說,它只會跳過當前目錄中的 .svn。

在 grep 2.5.1 中,您必須將此行添加到 ~/.bashrc 或 ~/.bash 配置文件

export GREP_OPTIONS="--exclude=\*.svn\*"

我發現 grepping grep 的輸出有時非常有幫助:

grep -rn "foo=" . | grep -v "Binary file"

盡管如此,這實際上並不能阻止它搜索二進制文件。

在 CentOS 6.6/Grep 2.6.3 上,我必須像這樣使用它:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

請注意缺少等號“=”(否則--include--excludeinclude-dir--exclude-dir將被忽略)

如果您不反對使用find ,我喜歡它的-prune功能:


find [directory] \
        -name "pattern_to_exclude" -prune \
     -o -name "another_pattern_to_exclude" -prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

在第一行,您指定要搜索的目錄。 . 例如,(當前目錄)是有效路徑。

在第 2 行和第 3 行,使用"*.png""*.gif""*.jpg"等。 使用盡可能多的這些-o -name "..." -prune構造,因為您有模式。

在第 4 行,您需要另一個-o (它指定“或”來find ),您需要的模式,並且您需要在它的末尾添加-print-print0 如果您只想要修剪*.gif*.png等圖像后保留的“其他所有內容”,請使用-o -print0並完成第 4 行。

最后,第 5 行是xargs的管道,它獲取每個結果文件並將它們存儲在變量FILENAME 然后它通過grep -IR標志, "pattern" ,然后FILENAMExargs擴展成為find的文件名列表。

對於您的特定問題,該聲明可能類似於:


find . \
     -name "*.png" -prune \
     -o -name "*.gif" -prune \
     -o -name "*.svn" -prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES

git grep

使用針對性能進行了優化並旨在搜索特定文件的git grep

默認情況下,它會忽略二進制文件,並且會尊重您的.gitignore 如果您不使用 Git 結構,您仍然可以通過傳遞--no-index來使用它。

示例語法:

git grep --no-index "some_pattern"

有關更多示例,請參閱:

我是一個業余愛好者,當然,但這是我的 ~/.bash_profile 的樣子:

export GREP_OPTIONS="-orl --exclude-dir=.svn --exclude-dir=.cache --color=auto" GREP_COLOR='1;32'

請注意,要排除兩個目錄,我必須使用 --exclude-dir 兩次。

目錄中還有許多二進制文件。 我不能只搜索某些目錄(目錄結構一團糟)。 有沒有更好的方法只在某些文件中進行 grepping?

ripgrep

這是旨在遞歸搜索當前目錄的最快工具之一。 它是用Rust編寫的,建立在Rust 的正則表達式引擎之上,以實現最高效率。 檢查這里詳細分析

所以你可以運行:

rg "some_pattern"

它尊重您的.gitignore並自動跳過隱藏的文件/目錄和二進制文件。

您仍然可以使用-g / --glob自定義包含或排除文件和目錄。 通配規則匹配.gitignore通配符。 檢查man rg尋求幫助。

有關更多示例,請參閱:如何使用 grep 排除與某些擴展名不匹配的某些文件?

在 macOS 上,您可以通過brew install ripgrep進行brew install ripgrep

find 和 xargs 是你的朋友。 使用它們來過濾文件列表而不是 grep 的 --exclude

嘗試類似的東西

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="

習慣這一點的好處是,它可以擴展到其他用例,例如計算所有非 png 文件中的行數:

find . -not -name '*.png' -o -type f -print | xargs wc -l

要刪除所有非 png 文件:

find . -not -name '*.png' -o -type f -print | xargs rm

等等。

正如評論中所指出的,如果某些文件的名稱中可能有空格,請改用-print0xargs -0

試試這個:

$ find . -name "*.txt" -type f -print | xargs file | grep "foo=" | cut -d: -f1

在這里成立: http : //www.unix.com/shell-programming-scripting/42573-search-files- exclude-binary- files.html

如果您以非遞歸方式搜索,則可以使用glop 模式來匹配文件名。

grep "foo" *.{html,txt}

包括 html 和 txt。 它只在當前目錄中搜索。

在子目錄中搜索:

   grep "foo" */*.{html,txt}

在子目錄中:

   grep "foo" */*/*.{html,txt}

這些腳本並不能解決所有的問題......試試這個更好:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

這個腳本非常好,因為它使用“真正的”正則表達式來避免搜索目錄。 只需用“\\|”分隔文件夾或文件名在 grep -v

好好享受! 在我的 linux shell 上找到了! XD

看看@這個。

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags

GNU grep--binary-files=without-match選項讓它跳過二進制文件。 (相當於其他地方提到的-I開關。)

(這可能需要最新版本的grep ;至少 2.5.3 有。)

適用於 tcsh .alias 文件:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

我花了一段時間才弄清楚 {mm,m,h,cc,c} 部分不應該在引號內。 ~基思

忽略來自 grep 的所有二進制結果

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

awk 部分將過濾掉所有二進制文件 foo 匹配的行

嘗試這個:

  1. 在 currdir .. 下創建一個名為“ --F ”的文件夾(或鏈接另一個重命名為“ --F ”的文件夾,即double-minus-F
  2. #> grep -i --exclude-dir="\\-\\-F" "pattern" *

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM