如何在Linux上查找包含特定文本的所有文件?
我试图find一种方法来扫描我的整个Linux系统的所有文件包含特定的文本string。 只是为了澄清,我正在寻找文件中的文本,而不是在文件名。
当我正在查找如何做到这一点时,我遇到了这个解决scheme两次:
find / -type f -exec grep -H 'text-to-find-here' {} \;
但是,它不起作用。 它似乎显示在系统中的每个单个文件。
这是否接近正确的方式来做到这一点? 如果不是,我该怎么办? 这种在文件中查找文本string的function对于我正在进行的一些编程项目来说是非常有用的。
执行以下操作:
grep -rnw '/path/to/somewhere/' -e 'pattern'
-
-r
或-R
是recursion的, -
-n
是行号, -
-w
表示匹配整个单词。 -
-l
(小写字母L)可以添加到只给出匹配文件的文件名。
除此之外,– --exclude
,– --include
,– --exclude-dir
或--include-dir
标志可用于高效search:
-
这将只search那些具有.c或.h扩展名的文件:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
-
这将排除search所有以.o扩展名结尾的文件:
grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
- 就像排除文件一样,可以通过
--exclude-dir
和--include-dir
参数排除/包含目录。 例如,这将排除目录dir1 /,dir2 /,并且它们全部匹配* .dst /:
grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
这对我来说非常好,可以达到和你一样的目的。
为更多选项检查man grep
。
你可以使用grep -ilR
:
grep -Ril "text-to-find-here" /
-
i
代表忽略大小写(在你的情况下可选)。 -
R
代表recursion。 -
l
代表“显示文件名,而不是结果本身”。 -
/
表示从你机器的根目录开始。
你可以使用ack 。 这就像grep的源代码。 您可以使用它扫描整个文件系统。
做就是了:
ack 'text-to-find-here'
在你的根目录下。
您也可以使用正则expression式 ,指定文件types等
UPDATE
我刚刚发现了Silver Searcher ,它比ack快了3-5倍,甚至忽略了.gitignore
文件中的模式。
您可以使用:
grep -r "string to be searched" /path/to/dir
r
代表recursion,因此将search指定的path及其子目录。 这会告诉你文件名以及打印string出现的文件中的行。
或者一个类似于你正在尝试的命令(例如:)在所有JavaScript文件(* .js)中search:
find . -name '*.js' -exec grep -i 'string to search for' {} \; -print
这将打印出现文本的文件中的行,但不打印文件名。
你可以使用这个:
grep -inr "Text" folder/to/be/searched/
如果你的grep
不支持recursionsearch,你可以把find
和xargs
结合起来:
find / -type f | xargs grep 'text-to-find-here'
我发现这比find -exec
的格式更容易记住。
这将输出文件名和匹配的行的内容,例如
/home/rob/file:text-to-find-here
您可能要添加到grep
可选标志:
-
-i
– 不区分大小写的search -
-l
– 只输出find匹配的文件名 -
-h
– 只输出匹配的行(不是文件名)
包含给定文本的文件名称列表
首先,我相信你用-H
代替-l
。 您也可以尝试添加引号内的文本,然后加上{} \
。
find / -type f -exec grep -l "text-to-find-here" {} \;
例
假设您正在search包含您的目录中的特定文本“Apache许可证”的文件。 它会显示类似于下面的结果(根据您的目录内容,输出会有所不同)。
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$
删除大小写敏感
即使你不使用关于“文本”与“文本”的情况,你可以使用-i
开关忽略大小写。 你可以在这里阅读更多的细节。
希望这可以帮助你。
grep -insr "pattern" *
-
i
:忽略PATTERN和input文件中的大小写区别。 -
n
:在input文件的前面输出每一行,以1为基准的行号。 -
s
:禁止关于不存在或不可读文件的错误消息。 -
r
:recursion读取每个目录下的所有文件。
尝试:
find . -name "*.txt" | xargs grep -i "text_pattern"
使用pwd
从您所在的任何目录search,向下recursion
grep -rnw `pwd` -e "pattern"
更新根据您使用的grep的版本,您可以省略pwd
。 在更新的版本.
似乎是缺省的情况下,如果没有给出目录,则为grep:
grep -rnw -e "pattern"
要么
grep -rnw "pattern"
会做同样的事情,如上所述!
如果您知道源文件的扩展名(并且该项目不太大),请使用:
grep "class foo" **/*.c
在您感兴趣的文件夹内。
这里的魔术是在使用扩展通配符( **
),它可以帮助您以特定的扩展名recursion扫描所有文件。 如果不起作用,请通过shopt -s globstar
激活。 您也可以使用**/*.*
作为所有文件(不包括隐藏和不带扩展名)。
添加以下有用的参数(对于源代码search最常见):
-
-i
– 对于不敏感的search, -
-w
– search单词(与部分单词匹配相反), -
-n
– 显示你的匹配行, -
--context=5
– 增加上下文,所以你更好地认识周围的代码, -
-color
– 用颜色标记匹配的文本(有时默认是有效的) -
-I
– 忽略二进制文件(通过指定文件扩展名,你实际上)。
如果您的论点太长,请考虑缩小search范围,或者使用find
语法。
有一个新的实用工具,称为Silversearcher
sudo apt install silversearcher-ag
它与Git和其他VCS密切合作。 所以你不会在.git或其他目录中得到任何东西。
你可以简单地使用
ag -ia "Search query"
它会为你做任务!
以下是可用于search文件的几个命令列表。
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
即使我们不查找string,也可以使用grep
。
简单地运行,
grep -RIl "" .
将打印出所有文本文件的path,即只包含可打印字符的文件。
尝试:
find / -type f -exec grep -H 'text-to-find-here' {} \;
这将search所有文件系统,因为/
是根文件夹。
对于家庭文件夹使用:
find ~/ -type f -exec grep -H 'text-to-find-here' {} \;
对于当前文件夹使用:
find ./ -type f -exec grep -H 'text-to-find-here' {} \;
find /path -type f -exec grep -l "string" {} \;
来自评论的解释
find是一个命令,用于查找给定path的子目录中的文件和其他对象,如目录和链接。 如果不指定文件名应该符合的掩码,则枚举所有目录对象。
-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
希望这是协助…
将grep
扩展一点,以便在输出中提供更多信息,例如,可以按如下方式获取文本所在文件中的行号:
find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"
如果您知道文件types是什么,则可以通过指定要search的文件types扩展名(在本例中为.pas
或.dfm
文件)缩小search范围:
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
embedded的grep
,允许文件名中带有空格的文件名的传递,允许grep将path和文件名视为一个string,而不是打破它在每个空间上。
一个简单的find
可以方便地工作。 在你的~/.bashrc
文件中~/.bashrc
别名:
alias ffind find / -type f | xargs grep
开始一个新的terminal,并发出:
ffind 'text-to-find-here'
我写了一个类似的Python脚本 。 这是如何使用这个脚本。
./sniff.py path pattern_to_search [file_pattern]
第一个参数path
是我们将recursionsearch的目录。 第二个参数pattern_to_search
是我们想要在文件中search的正则expression式。 我们使用Python库中定义的正则expression式格式。 在这个脚本中, 也匹配换行符。
第三个参数file_pattern
是可选的。 这是另一个正则expression式在文件名上工作。 只有那些匹配这个正则expression式的文件才会被考虑。
例如,如果我想search包含Pool(
的扩展名py
Python文件Pool(
接着是字Adaptor
,我执行以下操作,
./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
瞧,它会生成匹配的文件和行号的匹配path。 如果find多个匹配项,则每个行号都将被附加到文件名。
下面的命令对于这种方法可以正常工作:
find ./ -name "file_pattern_name" -exec grep -r "pattern" {} \;
使用:
grep -c Your_Pattern *
这将报告当前目录中每个文件中有多less个模式副本。
searchstring并用searchstring输出该行:
for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done
例如:
for i in $(find /usr/share/applications -type f); \ do grep -i "web browser" "$i"; done
要显示包含searchstring的文件名:
for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;
例如:
for i in $(find /usr/share/applications -type f); \ do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \ fi; done;
银search是一个了不起的工具,但ripgrep可能会更好。
它可以在Linux,Mac和Windows上运行,几个月前写在了Hacker News上 (这里有一个和Andrew Gallant的Blog有链接的链接):
Ripgrep – 一个新的命令行search工具
如果你有一组文件,你会一直检查你可以别名他们的path,例如:
alias fd='find . -type f -regex ".*\.\(inc\|info\|module\|php\|test\|install\|uninstall\)"'
那么你可以简单地过滤这样的列表:
grep -U -l $'\015' $(fd)
哪个过滤出列表fd到包含CR模式的文件。
我发现别名我感兴趣的文件可以帮助我创build更简单的脚本,然后总是试图记住如何获取所有这些文件。 recursion的东西也适用,但迟早你将不得不面对淘汰特定的文件types。 这就是为什么我只是find所有我感兴趣的文件types开始。
您可以使用下面的命令,因为您不需要文件名,但是要从所有文件中进行search。 这里是我从所有的日志文件捕获“TEXT”,确保文件名不打印:
# grep -e TEXT *.log | cut -d' ' --complement -s -f1
与其他选项相比,使用grep和-e
选项相当快,因为它是用于PATTERN匹配的。
避免麻烦并安装ack-grep。 它消除了许多许可和报价问题。
apt-get install ack-grep
然后转到您要search的目录并运行下面的命令
cd / ack-grep "find my keyword"
grep -Erni + "text you wanna search"
该命令将在当前目录的所有文件和目录中进行recursionsearch并打印结果。
注意:如果你的grep输出没有着色,你可以在你的shell src文件中使用grep ='grep –color = always'别名来改变它
尝试这个:
find . | xargs grep 'word' -sl
所有以前的答案build议grep和find。 但还有另一种方法:使用午夜指挥官
这是一个免费的实用程序(30岁,由时间certificate),这是视觉而不是GUI。 有大量的function,查找文件只是其中之一。
有一个确切的工具,可以做你正在寻找的东西。
http://linux.die.net/man/1/ack
ack -i search_string folder_path/*
您可以忽略-i
以区分大小写的search