bash扫描数百万个文件并快速扫描值

3 bash shell

我在文件夹中有数百万个文件(嵌套).我需要从这些文件中扫描一个值并打印包含该值的行(比方说LINE_TXT).早些时候,我曾经查过每个文件,但过去需要45分钟才能完成.我之前的解决方案是这样的:

FILES=$(find $1 -type f -name 'filename.txt')
for f in $FILES
do
    if [[ "$LINE" == *LINE_TXT* ]]; then
        echo $LINE
    fi
done
Run Code Online (Sandbox Code Playgroud)

我发现管道磨机是实现这一目标的最佳方式.我的主要解决方案是这样的:

makefifo mypipe
find $1 -type f -name 'filename.txt' | xargs cat > my pipe &
while read -r LINE
do
    if [[ "$LINE" == *LINE_TXT* ]]; then
        echo $LINE
    fi
done << mypipe
Run Code Online (Sandbox Code Playgroud)

运行时间是1分钟左右.我可以进一步提高吗?

gho*_*oti 5

在我看来,较少的脚本开销会使事情变得更快.

fgrep -r -h 'LINE_TXT' $1
Run Code Online (Sandbox Code Playgroud)

让grep通过你的目录做自己的递归-r.如果您不希望其输出在其输出中包含文件名,请包含该-h选项.您可以通过后处理所需的任何内容来管道输出.

如果您只想搜索特定的文件名,grep的-r选项有自己的选项:--include--exclude在其手册页中提到.例如:

fgrep -h -r --include '*/filename.txt' 'LINE_TXT' $1
Run Code Online (Sandbox Code Playgroud)

虽然find命令非常好,并且在某些情况下非常有用,但如果您可以使用内置于单个工具中的选项grep,则会产生较少的开销.该find命令不会查看文件内部,因此它仍然必须grep为每个文件启动.如果您想要使用find,它可能看起来像这样:

find $1 -name 'filename.txt' -exec fgrep 'LINE_EXT' {} \;
Run Code Online (Sandbox Code Playgroud)

这样可以让您访问find目录搜索功能,但如果您只想在目录树中查找特别命名的文件,那么grep -r --include可能就足够了,并且确保运行得更快.

  • @AndersJohansson - 更新为包含`--include` (2认同)
  • 另请注意,最后一个示例`find ... -exec fgrep ... \;`将为每个匹配启动一个新的`fgrep`实例; 这是非常低效的.如果您改为管道输出`xargs`,它将收集尽可能多的文件名,这些文件名将适合您的命令行(通常为数百或数千),并执行单个`fgrep`一次搜索所有这些文件,然后重复此过程,直到所有文件都有被搜查了. (2认同)