是否有更快的方法来编写此bash目录搜索字符串查询?

时间:2014-06-14 08:34:19

标签: bash unix

这是我在大约32K目录上运行的东西:

for f in $*
do
        N=`egrep Ended $f/jobLog.txt | wc -l`
        if [[ $N == 0 ]]
        then
                echo $f
        fi
done > /tmp/repairList

它运行但速度很慢 - 是一种更好的方法吗?

我想列出名为jobLog.txt的文件不包含字符串“Ended”的目录

2 个答案:

答案 0 :(得分:2)

在不知道目录和文件的外观以及是否有SSD或旋转磁盘的情况下,我不能说这是否会更快,但它应该使用所有内核并行搜索,这可能是显着的更快:

find . -name jobLog.txt | parallel -n 256 -m fgrep -L Ended {}

它使用GNU Parallel - here

为了好玩,我创建了32,000个目录,并在每个目录中放入一个名为jobLog.txt的文件,其中包含“独立宣言”的副本,其中包含"结束"添加到除100以外的所有内容并对它们进行基准测试差异是巨大的 - 看到包括的时间。 80秒对1.8秒。

#!/bin/bash
# METHOD1 - Original
for f in d*
do
        N=`egrep Ended $f/jobLog.txt | wc -l`
        if [[ $N == 0 ]]
        then
                echo $f
        fi
done

real    1m20.178s
user    0m50.072s
sys 1m9.040s

#!/bin/bash
# METHOD2 - use fgrep instead of egrep
for f in d*
do
        N=`fgrep -m1 Ended $f/jobLog.txt | wc -l`
        if [[ $N == 0 ]]
        then
                echo $f
        fi
done

real    1m14.052s
user    0m48.253s
sys 1m5.962s

#!/bin/bash
# METHOD3 - avoid creating 32,000 "wc" processes
for f in d*
do
        fgrep -m1 -q Ended $f/jobLog.txt
        if [[ $? != 0 ]]
        then
              echo $f
        fi
done

real    0m52.412s
user    0m22.542s
sys 0m28.680s

#!/bin/bash
# METHOD4 - Use GNU Parallel
find . -name jobLog.txt | parallel -n 256 -m fgrep -L Ended {} 

real    0m1.850s
user    0m3.211s
sys 0m1.400s

答案 1 :(得分:1)

只需使用fgrep-L和特殊扩展:

fgrep -L -e Ended -- "${@/%//jobLog.txt}" | sed -e 's|/jobLog.txt||' > /tmp/repairList

也许某些工具可能比sed更快,例如awkcut,但不会带来显着收益,特别是如果只有32k行。重要的是,您不要多次拨打fgrep,而只是让它执行列表,而不是运行循环并echoing每一个。

任何想要窃取这个概念的人都可以创建一个Awk脚本,它可以结合fgrepsed的作业。