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

bash扫描数百万个文件并快速扫描一个值,bash,shell,Bash,Shell,我在一个文件夹中有数百万个文件(嵌套)。我需要扫描这些文件中的一个值,并打印包含该值的行(例如LINE\u TXT)。早些时候,我曾对每个文件进行sed,但这通常需要45分钟。我以前的解决方案是这样的: FILES=$(find $1 -type f -name 'filename.txt') for f in $FILES do if [[ "$LINE" == *LINE_TXT* ]]; then echo $LINE fi done makefifo m

我在一个文件夹中有数百万个文件(嵌套)。我需要扫描这些文件中的一个值,并打印包含该值的行(例如
LINE\u TXT
)。早些时候,我曾对每个文件进行sed,但这通常需要45分钟。我以前的解决方案是这样的:

FILES=$(find $1 -type f -name 'filename.txt')
for f in $FILES
do
    if [[ "$LINE" == *LINE_TXT* ]]; then
        echo $LINE
    fi
done
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
find $1 -name 'filename.txt' -exec fgrep 'LINE_EXT' {} \;
我发现管道磨是实现这一目标的最好方法。我的主要解决方案如下:

FILES=$(find $1 -type f -name 'filename.txt')
for f in $FILES
do
    if [[ "$LINE" == *LINE_TXT* ]]; then
        echo $LINE
    fi
done
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
find $1 -name 'filename.txt' -exec fgrep 'LINE_EXT' {} \;
makefifomypipe
查找$1-键入f-name'filename.txt'| xargs cat>my pipe&
而read-r行
做
如果[[“$LINE”==*LINE_TXT*];然后
回音$线
fi

完成是的,
查找$1-type f-name'filename.txt'| xargs fgrep LINE_txt
,如果您只想在这些文件中找到“LINE_txt”的所有匹配项。

在我看来,脚本开销越小,事情就越快

fgrep -r -h 'LINE_TXT' $1
只要让grep使用
-r
在您的目录中进行自己的递归即可。如果您不希望其输出包含文件名,请包含
-h
选项。您可以通过管道将其输出传输到任何需要进行后处理的地方

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

fgrep -h -r --include '*/filename.txt' 'LINE_TXT' $1
虽然
find
命令非常出色,在某些情况下非常有用,但如果您可以使用内置于单个工具(如
grep
)中的选项,那么开销就会减少。
find
命令不会查看文件内部,因此它仍然必须为每个文件启动
grep
。如果您确实想使用
查找
,它可能如下所示:

FILES=$(find $1 -type f -name 'filename.txt')
for f in $FILES
do
    if [[ "$LINE" == *LINE_TXT* ]]; then
        echo $LINE
    fi
done
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
find $1 -name 'filename.txt' -exec fgrep 'LINE_EXT' {} \;

这样做的好处是,您可以访问
find
的目录搜索功能,但如果您只想在目录树中查找特定命名的文件,grep的
-r--include
可能就足够了,而且肯定会运行得更快。

遗憾的是,我需要进一步处理这些行以提取更多信息。如何处理?例如,如果通过脚本/其他命令,您可以通过管道:
find…|xargs fgrep…|处理
在这种情况下,您应该使用
查找$1-键入f-name'filename.txt'| xargs fgrep-H LINE_txt,这样它也会打印文件名,然后再处理。@ZsoltBotykai-不,您不应该这样做。阅读如果您想在
find
找到的文件上执行操作,您确实需要了解如何使用
-exec
执行操作。如果文件名包含一些愚蠢的字符,如空格或其他,您可以通过以下方式使用从
find
传递到
xargs
的以零结尾的字符串:
find$1-键入f-name'file*.txt'-print0 | xargs-0 grep-H LINE_txt
如果您想搜索所有文件,此操作有效;如果您想进行更具体的搜索(使其运行更快),
find
选项更好。是的,每个文件夹中都有不同名称的文件,我想搜索文件名为filename的特定文件。txt@AndersJohansson-更新为包含
--包含
@ghoti,有趣-不知道
--包含
。就我个人而言,我仍然更喜欢
find
,因为它有更多的选项,如按权限查找、是否遵循符号链接等。但是对于这个问题,您的答案可能运行得更快。还要注意最后一个示例,
find-执行主任fgrep…\
将为每个匹配启动一个新的
fgrep
实例;这是非常低效的。如果您改为使用管道连接到
xargs
,它将收集尽可能多的文件名(通常是数百个或数千个),并执行一次
fgrep
搜索所有这些文件,然后重复该过程,直到搜索完所有文件。