我的目录包含cca 26 000个文件,我需要在所有这些文件中进行grep。问题是,我需要尽可能快的速度,因此制作grep从find命令获取一个文件的名称并将匹配项写入文件的脚本不是理想的。在出现“参数列表过长”之前,cca花了2分钟时间在所有这些文件中进行grep。有什么想法怎么做?编辑:有一个脚本一直在制作新文件,因此不可能将所有文件放在不同的目录中。
我的目录包含cca 26 000个文件,我需要在所有这些文件中进行grep。问题是,我需要尽可能快的速度,因此制作grep从find命令获取一个文件的名称并将匹配项写入文件的脚本不是理想的。在出现“参数列表过长”之前,cca花了2分钟时间在所有这些文件中进行grep。有什么想法怎么做?编辑:有一个脚本一直在制作新文件,因此不可能将所有文件放在不同的目录中。
Answers:
与find
:
cd /the/dir
find . -type f -exec grep pattern {} +
(-type f
仅用于搜索常规文件(即使符号链接指向常规文件也除外)。如果要搜索除目录以外的任何类型的文件(但请注意,有些类型的文件如fifos或/ dev / zero你一般不想读),更换-type f
用GNU特定的! -xtype d
(-xtype d
对于文件类型匹配目录符号链接分辨率后))。
使用GNU grep
:
grep -r pattern /the/dir
(但是请注意,除非您具有最新版本的GNU grep,否则当进入目录时,它将遵循符号链接)。除非添加-D read
选项,否则不会搜索非常规文件。不过,最新版本的GNU grep
仍不会在符号链接中搜索。
非常老的GNU版本find
不支持标准{} +
语法,但是您可以使用非标准语法:
cd /the/dir &&
find . -type f -print0 | xargs -r0 grep pattern
性能可能受I / O约束。那是进行搜索的时间,就是从存储中读取所有数据所需的时间。
如果数据位于冗余磁盘阵列上,则一次读取多个文件可能会提高性能(否则可能会使它们降级)。如果性能不受I / O限制(例如,因为所有数据都在缓存中),并且您有多个CPU,那么并发greps
也可能会有所帮助。您可以使用GNU xargs
的-P
选项来实现。
例如,如果数据位于具有3个驱动器的RAID1阵列上,或者数据位于高速缓存中,并且您有3个CPU的空闲时间:
cd /the/dir &&
find . -type f -print0 | xargs -n1000 -r0P3 grep pattern
(此处-n1000
用于grep
每1000个文件生成一个新文件,一次最多并行运行3个文件)。
但是请注意,如果grep
重定向了的输出,最终将导致来自3个grep
进程的交错输出,在这种情况下,您可能希望将其运行为:
find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern
(在最新的GNU或FreeBSD系统上)或使用--line-buffered
GNU选项grep
。
如果pattern
为固定字符串,则添加-F
选项可以改善问题。
如果不是多字节字符数据,或者对于该模式的匹配,则数据是否为多字节字符都没有关系,则:
cd /the/dir &&
LC_ALL=C grep -r pattern .
可以显着提高性能。
如果您最终经常进行此类搜索,则可能需要使用众多搜索引擎之一为数据建立索引。
对于大多数文件系统,单个目录中的26000个文件很多。可能会花费大部分时间来读取这个大目录。考虑将其拆分为较小的目录,每个目录仅包含数百个文件。
find
除非做错了,否则呼叫无法解释性能不佳。这是遍历目录的一种快速方法,并且可以确保您不会冒险尝试执行太长的命令行。确保使用-exec grep PATTERN {} +
,每个命令调用可以打包尽可能多的文件,而不要使用-exec grep PATTERN {} \;
,grep
每个文件只能执行一次:每个文件执行一次命令的速度可能会大大降低。
如果您需要多次grep所有文件(如您所说,运行脚本),我建议查看ram磁盘,复制所有文件,然后多次grep文件,这将使您的搜索速度提高一倍至少100倍。
您只需要足够的内存。否则,您应该考虑建立文件索引,例如。进入lucene或nosql数据库,然后在其上运行查询。
grep
。还有一点要指出:“有一个脚本一直在制作新文件,因此不可能将所有文件放在不同的目录中。”
目录中的所有文件
grep 'search string' *
递归地
grep -R 'search string' *
.
而不是会有所帮助*
)。*
将排除点文件(尽管使用-R,但不包括递归目录中的文件)。-R与-r相反,即使在最新版本的GNU grep中也遵循符号链接。您还可以在当前目录中的名称文件的问题开头-
find
与xargs
grep -R