这是我在大约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”的目录
答案 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
更快,例如awk
或cut
,但不会带来显着收益,特别是如果只有32k行。重要的是,您不要多次拨打fgrep
,而只是让它执行列表,而不是运行循环并echoing
每一个。
任何想要窃取这个概念的人都可以创建一个Awk脚本,它可以结合fgrep
和sed
的作业。