如何在 Linux 上找到包含特定文本的所有文件?

linux text grep directory find

想要改进这篇文章?提供这个问题的详细答案,包括引文和解释为什么你的答案是正确的。没有足够细节的答案可能会被编辑或删除。

如何在文件内容中找到包含特定文本字符串的所有文件?

以下不起作用。它似乎显示了系统中的每个文件。

find / -type f -exec grep -H 'text-to-find-here' {} \;

请记住,grep 会将任何 . 解释为单字符通配符等。我的建议是始终使用 fgrep 或 egrep。

不管怎样,你快到了!只需将 -H 替换为 -l(也可以将 grep 替换为 fgrep)。要排除具有特定名称模式的文件,您可以使用 find 以更高级的方式。不过,学习使用 find 是值得的。只需 man find

find … -exec <cmd> +find … -exec <cmd> \; 更容易输入且速度更快。它仅在 <cmd> 接受任意数量的文件名参数时才有效。如果 <cmd> 像 Python 或 Ruby 脚本一样启动缓慢,则执行时间的节省尤其大。

要在给定路径中进行非递归搜索,命令是 `grep --include=*.txt -snw "pattern" thepath/*。

这个问题应该在 Unix-Linux 社区上。

M
Mateen Ulhaq

请执行下列操作:

grep -rnw '/path/to/somewhere/' -e 'pattern'

-r 或 -R 是递归的,

-n 是行号,并且

-w 代表匹配整个单词。

-l(小写 L)可以添加以仅给出匹配文件的文件名。

-e 是搜索过程中使用的模式

除了这些,--exclude--include--exclude-dir 标志可用于高效搜索:

这只会搜索具有 .c 或 .h 扩展名的文件:

grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"

这将排除搜索所有以 .o 扩展名结尾的文件:

grep --exclude=\*.o -rnw '/path/to/somewhere/' -e "pattern"

对于目录,可以使用 --exclude-dir 参数排除一个或多个目录。例如,这将排除目录 dir1/、dir2/ 以及所有匹配 *.dst/ 的目录:

grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"

这对我来说非常有效,可以实现与您几乎相同的目的。

有关更多选项,请参阅 man grep

使用--排除。像 "grep -rnw --exclude=*.o 'directory' -e "pattern"

值得注意的是:似乎 r 选项是惰性的(首先遍历深度,而不是在第一个目录之后停止),而 R 是贪婪的(将正确遍历整个树)。

grep -rnw "String I was looking for" 完成了我需要的操作。谢谢!

注意(尤其是新手):上述命令中的引号很重要。

@Eliran Malka Rr 都将正确遍历目录,但 R 将遵循符号链接。

M
Mateen Ulhaq

使用 grep -ilR

grep -Ril "text-to-find-here" /

i 代表忽略大小写(在您的情况下是可选的)。

R代表递归。

l 代表“显示文件名,而不是结果本身”。

/ 代表从机器的根目录开始。

根据我的经验,-i 会使它变慢很多,所以如果没有必要就不要使用它。在某个目录中对其进行测试,然后进行概括。它应该在几分钟内完成。我认为正则表达式会使它变慢。但是我的评论是基于假设的,我建议您在行前使用 time 进行测试。

是的,/* 代表它。无论如何,我刚刚对其进行了测试,发现只有 / 有效。

如果您不使用正则表达式进行搜索,则可以在大多数系统上使用 fgrep 代替 grep。

是的@markle976,实际上来自 man grep: fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings

您可以将 / 替换为目录 grep -Ril "text-to-find-here" ~/sites/ 的路径或使用 .当前目录 grep -Ril "text-to-find-here" .

R
RAJ

您可以使用 ack。它类似于源代码的 grep。您可以使用它扫描整个文件系统。

做就是了:

ack 'text-to-find-here'

在您的根目录中。

您还可以使用 regular expressions,指定文件类型等。

更新

我刚刚发现 The Silver Searcher,它类似于 ack,但比它快 3-5 倍,甚至忽略了 .gitignore 文件中的模式。

非常有用,简单,快速。警告:“在 Debian 派生的发行版上,ack 被打包为“ack-grep”,因为“ack”已经存在”(来自 beyondgrep.com/install)。您最终可能会在这些 Linux 上运行汉字代码转换器......

ack 或 ack-grep 有很好的亮点,但 find+grep 正确使用时性能要好得多

请注意,ripgrep 比此处提到的任何其他内容都快,包括 The Silver Searcher 和普通的 'ol grep。参见this blog post 以获取证据。

V
Vivek Ranjan

您可以使用:

grep -r "string to be searched"  /path/to/dir

r 代表递归,因此将在指定的路径及其子目录中进行搜索。这将告诉您文件名并打印出文件中出现字符串的行。

或类似于您正在尝试的命令(例如:)在所有 javascript 文件 (*.js) 中搜索:

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

这将打印文件中出现文本的行,但不打印文件名。

除了这个命令,我们也可以这样写: grep -rn "String to search" /path/to/directory/or/file -r: recursive search n: 将显示匹配的行号

感谢您的“查找”版本!能够通过 '.js' 或 '.txt' 等进行过滤非常重要。没有人愿意花费数小时等待 grep 完成对上次家庭度假的所有数 GB 视频的搜索,即使命令是更容易打字。

M
Mateen Ulhaq

带有行号的递归和不区分大小写的 grep:

grep -inr "Text" folder/to/be/searched/

如果添加 -A3 会更好

-i 不区分大小写,-n 显示行号,-r 递归读取子目录中的所有文件

H
Hasidul Islam

grep(GNU 或 BSD)

您可以使用 grep 工具递归搜索当前文件夹,例如:

grep -r "class foo" .

注意:-r - 递归搜索子目录。

您还可以使用通配符语法在特定文件中进行搜索,例如:

grep "class foo" **/*.c

注意:通过使用 globbing option (**),它递归地扫描具有特定扩展名或模式的所有文件。 要启用此语法,请运行:shopt -s globstar您还可以将 **/*.* 用于所有文件(不包括隐藏且无扩展名)或任何其他模式。

如果您遇到参数太长的错误,请考虑缩小搜索范围,或改用 find 语法,例如:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

或者,使用 ripgrep

ripgrep

如果您正在处理较大的项目或大文件,则应改用 ripgrep,例如:

rg "class foo" .

查看 GitHub project page 上的文档、安装步骤或源代码。

它比任何其他工具(如 GNU/BSD grepucgagsiftackpt 或类似工具都快得多,因为它构建在 {9 之上它使用有限自动机、SIMD 和积极的文字优化来使搜索非常快速。

它支持在 .gitignore 文件中指定的忽略模式,因此单个文件路径可以同时与多个 glob 模式匹配。

您可以使用常用参数,例如:

-i - 不敏感搜索。

-I - 忽略二进制文件。

-w - 搜索整个单词(与部分单词匹配相反)。

-n - 显示匹配的行。

-C/--context (eg -C5) - 增加上下文,所以你可以看到周围的代码。

--color=auto - 标记匹配的文本。

-H - 显示找到文本的文件名。

-c - 显示匹配行数。可以与 -H 结合使用。

我还发现扩展通配符很有用。但请记住,如果文件数量确实很大,您可能会收到“参数列表太长”错误。 (简单的 globbing 也容易出现这种错误)。

l
lkamal

包含给定文本的文件名列表

首先,我相信您使用的是 -H 而不是 -l。您也可以尝试在引号内添加文本,后跟 {} \

find / -type f -exec grep -l "text-to-find-here" {} \; 

例子

假设您正在目录中搜索包含特定文本“Apache License”的文件。它将显示类似于下面的结果(输出将根据您的目录内容而有所不同)。

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

删除区分大小写

即使您不使用“text”与“TEXT”之类的大小写,也可以使用 -i 开关忽略大小写。您可以阅读更多详细信息here

希望这对您有所帮助。

该命令的作用是:find 会将它找到的所有路径传递给命令 grep -l "text-to-find-here" <file found>"。您可以对文件名添加限制,例如 find / -iname "*.txt" 只搜索名称以 .txt 结尾的文件

@Auxiliary - 包含一个示例输出以避免读者混淆。

@Mene 这是一个真正可悲的状态,辅助的评论比你的投票多......即使他们的评论来自 2014 年,而你的评论是 2017 年,他们的评论有 6,而它应该正好是 0,而你的评论只有一个(现在是两个)是这不是我愿意相信的。

@Mene 据说 -iname 不区分大小写,这意味着它还会找到 .TXT 文件,例如,以及 TxT 和 TXt 等。

P
Peter Mortensen

当您在 Linux 上搜索特定文本时,此 grep 命令将为您提供精确的结果 -

grep -inRsH "Text to be searched" /path/to/dir (it can be '.')

i 代表忽略大小写区别

代表递归,它还包括符号链接。最好使用“R”而不是“r”

代表“它将打印行号”。

s 代表“抑制错误消息”

H 代表“它将打印每个匹配的文件名”

但这不会显示包含该文本的“文件”

此组合将为您提供 lineno、文件名以及您搜索的文本。 @FiruzzZ 尝试一次

R
RobEarl

如果您的 grep 不支持递归搜索,您可以将 findxargs 结合起来:

find / -type f | xargs grep 'text-to-find-here'

我发现这比 find -exec 的格式更容易记住。

这将输出匹配行的文件名和内容,例如

/home/rob/file:text-to-find-here

您可能要添加到 grep 的可选标志:

-i - 不区分大小写的搜索

-l - 只输出找到匹配的文件名

-h - 只输出匹配的行(不是文件名)

如果 find 没有找到任何内容,这相当于没有文件名的 grep 'text-to-find-here'。这将挂起并等待用户输入!将 --no-run-if-empty 作为选项添加到 xargs

如果文件或目录名称包含空格(xargs 解释为分隔符的字符),则 find 和 xargs 的这种组合不会按预期工作。使用 find … -exec grep … +。如果您坚持将 find 与 xargs 一起使用,请使用 -print0-0

F
Fabio Poloni
grep -insr "pattern" *

i:忽略 PATTERN 和输入文件中的大小写区别。

n:在其输入文件中使用从 1 开始的行号作为每行输出的前缀。

s:抑制有关不存在或不可读文件的错误消息。

r:递归读取每个目录下的所有文件。

您能否解释一下您的答案如何比其他答案有所改进,或者它与其他答案有何不同?

记住并不复杂,将涵盖所有模式(区分大小写 -> 关闭,包括文件名和行号,并将进行递归搜索等),最后使用“*”将搜索所有目录(无需指定任何路径或目录名称)。

抱歉,我应该更清楚:如果您可以在答案中包含该解释,那就太好了。就目前而言,尤其是已经有很多其他类似的答案,很难从如此简短的答案中看出尝试它对接受的答案或赞成的答案之一有什么好处。

@AmosM.Carpenter 我喜欢这个答案的一件事是指出了抑制参数,它可以帮助过滤掉与获得我们真正想要的结果无关的噪音。 Grep 在某些“文件”上打印诸如“功能未实现”、“无效参数”、“资源不可用”等错误。

@leetNightshade:我假设您正在向我发表评论,因为我要求对稀疏的原始帖子进行解释。请参阅 Fabio 的精彩 revision 以了解我之前的评论。

N
Neil Agarwal

有一个名为 The Silversearcher 的新实用程序

sudo apt install silversearcher-ag

它与 Git 和其他 VCS 密切合作。所以你不会在 .git 或其他目录中得到任何东西。

你可以简单地使用

ag "Search query"

它会为你完成任务!

好决定!。我第一次下载并使用它。输出结果信息量很大,色彩丰富,很有帮助。这个编将永远留在我的机器中。我也把它放在我的“安装新电脑”程序列表中。干杯!!

B
Bludzee

如何在 Linux 上找到包含特定文本的所有文件? (...) 我两次遇到这个解决方案: find / -type f -exec grep -H 'text-to-find-here' {} \;

如果在您的示例中使用 find,最好将 -s (--no-messages) 添加到 grep,并在命令末尾添加 2>/dev/null 以避免大量 权限grepfind 发出的拒绝消息:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find 是在类 Unix 平台上搜索文件的标准工具 - 在查找特定文本时与 grep 结合使用。顺便说一下,find 命令通常与 xargs 结合使用。

出于相同目的,存在更快、更简单的工具 - 见下文。最好尝试一下,前提是它们可以在您的平台上使用,当然:

更快更简单的替代方案

RipGrep - 最快的搜索工具:

rg 'text-to-find-here' / -l

The Silver Searcher

ag 'text-to-find-here' / -l

ack

ack 'text-to-find-here' / -l

注意:您也可以将 2>/dev/null 添加到这些命令中,以隐藏许多错误消息。

警告除非你真的无法避免,否则不要从 '/' (the root directory) 搜索,以免搜索时间长且效率低!因此,在上面的示例中,您最好将“/”替换为子目录名称,例如“/home”,具体取决于您实际要搜索的位置...

k
kenorb

尝试:

find . -name "*.txt" | xargs grep -i "text_pattern"

这实际上是什么时候不使用 xargs 这样的一个主要示例.. 考虑一下。 echo "file bar.txt has bar" > bar.txt; echo "file foo bar.txt has foo bar" > "foo bar.txt"; echo "You should never see this foo" > foo; find . -name "*.txt" | xargs grep -i foo # ./foo:You should never see this foo 。此处的 xargs 与错误文件匹配,与预期文件不匹配。要么使用 find .. -print0 | xargs -0 ...,但这是无用的管道或更好的 find ... -exec grep ... {} +

E
Eyni Kave
grep -lrnw '/root/Desktop/ipozal' -e 'geolocation'

例如:

我的文件夹名称是“ipozal”

它放在“/root/Desktop”上

我想在“地理位置”中的所有文件上找到此文本

欢迎来到堆栈溢出!请考虑为此代码块添加描述或解释。

1.在桌面备份您的文件夹

2.我的项目名称是'ipozal'

然后使用此命令并将“ipozal”替换为您的文件夹名称,以查找包含此文本“地理位置”的文件

很好的解释——你应该编辑你的答案,以便包含解释。

m
mahatmanich

使用 pwd 从您所在的任何目录中搜索,向下递归

grep -rnw `pwd` -e "pattern"

更新 根据您使用的 grep 版本,您可以省略 pwd。如果没有给出目录,则在较新的版本上 . 似乎是 grep 的默认情况:

grep -rnw -e "pattern"

或者

grep -rnw "pattern"

会做和上面一样的事情!

根本不需要使用 pwd,因为它是默认设置。 grep -rnw "pattern" 就足够了。

事实上 grep -rnw 和类似的答案就像三年前一样,我看不出这个答案是如何增加价值的。

选择的答案没有显示默认模式,5 个人似乎发现它很有用

“默认模式”是什么意思?接受的答案包含 grep -rnw '/path/to/somewhere/' -e "pattern",这就是您在此处所拥有的。 230 万次访问后获得 5 票并不意味着什么。

我同意 :-) 我在原始答案中缺少的是您根本不必提供路径或递归搜索当前目录的用例,这未反映在已接受的答案中。因此,深入了解 grep 是一次很好的学习经历。

P
Peter Mortensen

即使我们不是在寻找字符串,也可以使用 grep

简单的跑步,

grep -RIl "" .

将打印出所有文本文件的路径,即那些只包含可打印字符的文件。

我看不出这比仅使用 lsfind (用于递归)更好

J
JMP

如果您严格要使用 find,请使用 find + grep

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

脚步:

使用 find 搜索文件,对所有文件执行 grep。

这使您可以使用 find 查找文件。

如果您只想 grep 某些文件,请使用 -name Pattern:

find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

您可以使用 find 的不同选项来改进文件搜索。

有什么区别?它可以与文件路径中的空格一起使用吗?

不提供找到的文件的文件名。

A
Atul Arvind

以下是可用于搜索文件的几个命令列表。

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path

这对现有答案有什么补充?

@fedorqui egrep 等同于 grep -E 表示 --extended-regexp 您可以在此处找到详细信息 unix.stackexchange.com/a/17951/196072

P
Peter Mortensen

Silver Searcher 是一个了不起的工具,但 ripgrep 可能会更好。

它适用于 Linux、Mac 和 Windows,几个月前在 Hacker News 上写过(这里有 Andrew Gallant 博客的链接,其中有一个 GitHub 链接):

Ripgrep – A new command line search tool

P
Peter Mortensen

如果您在 Git 存储库中,则可以使用:

git grep something

出于好奇,这是否仅检查已签入 git 和/或未签入 .gitignore 文件的文件?只是检查以确保,因为我喜欢在目录已经是 git 存储库的大多数开发情况下这是多么方便。

@JoshuaPinter 为您录制了一个 asciicinema asciinema.org/a/g92UTPtL929ysb8umqPj9e2SA 这个想法是 git grep 搜索 git 中的内容,无论是提交的还是隐藏的。当您忽略一个文件并且它没有提交或隐藏时,它不会出现在 git grep

@Dorian 很棒。感谢您确认这个想法。如果您不知道,这可能是一个令人讨厌的问题。再次感谢。

P
Peter Mortensen

我对 grep 使用 'rl' 的简单程度着迷:

grep -rl 'pattern_to_find' /path/where/to/find

-r to recursively find a file / directory inside directories..
-l to list files matching the 'pattern'

使用不带 'l' 的 '-r' 来查看文件名,后跟找到模式的文本!

grep -r 'pattern_to_find' /path/where/to/find

它工作得非常完美......

这也适用于 Git Bash (Windows)。

但这意味着必须搜索每个文件(文件名或文件扩展名级别没有过滤器,如 .txt)。或者有没有办法做到这一点?

P
Peter Mortensen

希望这对您有帮助...

稍微扩展 grep 以在输出中提供更多信息,例如,获取文本所在文件中的行号,可以按如下方式完成:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

如果您知道文件类型是什么,您可以通过指定要搜索的文件类型扩展名来缩小搜索范围,在本例中为 .pas.dfm 文件:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

选项的简短说明:

.在 find 中指定从当前目录。 -name "*.*" :对于所有文件( -name "*.pas" -o -name "*.dfm" ):仅 *.pas 或 *.dfm 文件,或使用 -o -type f 指定您在 | 的另一侧寻找文件 -print0 和 --null (pipe) 是关键,将文件名从 find 传递给嵌入在 xargs 中的 grep,允许在文件名中传递带有空格的文件名,允许 grep 将路径和文件名视为一个字符串,而不是破坏它在每个空间上。

-name '*.*' 不是您所说的;它不会拾取名为“文件”的文件,因为该模式不等同于该文件(没有 .ext);但是 * 会(除了 . 文件)。但是还有另一件事:如果您想要所有文件,为什么还要首先指定文件名?没有其他评论 - 除了很高兴知道仍然有人不使用 MS 术语“文件夹”(真的在说够之后我不会添加,但我想指出你所做的稍微不正确的陈述带有文件名 - 以及“全部”情况下的冗余/无用)。

P
Peter Mortensen
grep "text-to-find-here" file_name

或者

grep "text-to-find-here" directory_path/*

如果要搜索当前目录:

grep "text-to-find-here" *

如果您要递归查看子目录,请确保在 grep 之后添加一个 -r 开关。

J
JuanZe
find /path -type f -exec grep -l "string" {} \;

来自评论的解释

find 是一个命令,可让您在给定路径的子目录中查找文件和其他对象,例如目录和链接。如果您未指定文件名应满足的掩码,它将枚举所有目录对象。

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
k
kenorb

尝试:

find / -type f -exec grep -H 'text-to-find-here' {} \;

它将搜索所有文件系统,因为 / 是根文件夹。

对于主文件夹使用:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

对于当前文件夹使用:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;

也许文件夹差异的细节对许多人来说是显而易见的......但对新手也很有帮助。 +1

这对现有答案有什么补充?

称它为我的十字军东征,但这个词是“目录”。这不是 Windows(过去一直使用“目录”——9x 之前)。请停止说“文件夹”。至于你的最后一个命令,你甚至不需要'/',仅供参考。

P
Peter Mortensen

一个简单的 find 可以很方便地工作。在您的 ~/.bashrc 文件中为其命名:

alias ffind find / -type f | xargs grep

启动一个新终端并发出:

ffind 'text-to-find-here'
D
Daniel

有一个 ack 工具可以完全满足您的需求。

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

对于区分大小写的搜索,您可以忽略 -i

这对现有答案有什么补充?这在三年多前就已经提出了。

@fedorqui 1)没有管道! 2) 使用正则表达式 3) 获取行号、带有相对路径的文件名、突出显示的文本等,对搜索后的编辑很有用,例如“vim +lineno path/file.cpp”会让你在不感兴趣的行上正确。请参阅命令“ack include\|hpp”的输出,该命令在我的搜索文件夹和子文件夹下搜索“include”或“hpp”关键字。我希望这一点很清楚。这是示例输出(不能用简单的文本显示关键字突出显示) process/child.hpp 11:boost/process/child.hpp process/all.hpp 21:#include

P
Peter Mortensen

grep 是您实现这一目标的好朋友。

grep -r <text_fo_find> <directory>

如果您不关心要查找的文本的大小写,请使用:

grep -ir <text_to_find> <directory>

在我的情况下,即使我指定了目录,它看起来也到处搜索

@Pathros 可能与启用递归以及您指定的目录有关。换句话说,递归确实以这种方式改变了事情。

@Pathros 哦,如果搜索字符串中有任何 - ,您需要先将 -- 传递给 grep;否则会引起有趣的副作用!

P
Peter Mortensen

我写了一个Python script,它做了类似的事情。这就是人们应该如何使用这个脚本。

./sniff.py path pattern_to_search [file_pattern]

第一个参数 path 是我们将在其中递归搜索的目录。第二个参数 pattern_to_search 是我们要在文件中搜索的正则表达式。我们使用 Python re 库中定义的正则表达式格式。在此脚本中,. 也匹配换行符。

第三个参数 file_pattern 是可选的。这是另一个适用于文件名的正则表达式。只有那些匹配这个正则表达式的文件才会被考虑。

例如,如果我想搜索扩展名为 py 且包含 Pool( 后跟单词 Adaptor 的 Python 文件,我执行以下操作,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

瞧,它会生成匹配文件的路径和找到匹配项的行号。如果找到多个匹配项,则每个行号都将附加到文件名中。

P
Peter Mortensen

以前的所有答案都建议使用 grep 和 find。但还有另一种方法:使用 Midnight Commander

它是一个免费的实用程序(已有 30 年历史,已被时间证明),它是可视的,而不是 GUI。它有很多功能,查找文件只是其中之一。

护林员会有同样的想法