如何在搜索后打印所有具有相同前缀的文件



我需要搜索一个包含许多子目录的目录,每个子目录都包含文件。文件如下所示:问题1234_01,其中1234是随机数字,后缀_01是包含前缀的消息数,这意味着它们是同一个连续线程的一部分。

find . -name 'quest*' | cut -d_ -f1  | awk '{print $1}' | uniq -c | sort -n  

示例输出:

1 quest1234    
10 quest1523

这将搜索所有文件,然后按顺序对它们进行排序。

我想做的是打印所有出现次数最多的文件,在我的例子中是10个匹配的文件。

因此它应该只输出quest1523_01quest1523_11

如果我理解你的意思,并且你想获得一个按频率排序的项目列表,你可以通过以下方式进行传输:

| sort | uniq -c | sort -k1nr

例如:

输入:

file1
file2
file1
file1
file3
file2
file2
file1
file4

输出:

4 file1
3 file2
1 file3
1 file4

更新

顺便问一下,你用awk干什么?

find . -name 'quest*' | cut -d_ -f1  | sort | uniq -c | sort -k1nr | head -n10

返回发现频率较高的10个项目。

更新

这是一个大大改进的版本。唯一的缺点是,它是而不是按出现次数排序。然而,我要想办法解决它:)

find . -name 'question*' | sort 
| sed "s#(.*/question([0-9]+)_[0-9]+)#2 1#" 
| awk '{ cnt[$1]++; files[$1][NR] = $2 } END{for(i in files){ print i" ("cnt[i]")"; for (j in files[i]) { print "    "files[i][j] } }}'

更新

在对大约140万条记录进行测试后(花了23英寸),我认为awk的效率太低,无法处理所有的分组内容等,所以我用Python写了这篇文章:

#!/usr/bin/env python
import sys, re
file_re = re.compile(r"(?P<name>.*/question(?P<id>[0-9]+)_[0-9]+)")
counts = {}
files = {}
if __name__ == '__main__':
for infile in sys.stdin:
infile = infile.strip()
m = file_re.match(infile)
_name = m.group('name')
_id = m.group('id')
if not _id in counts:
counts[_id] = 0
counts[_id]+=1
if not _id in files:
files[_id] = []
files[_id].append(_name)
## Calculate groups
grouped = {}
for k in counts:
if not counts[k] in grouped:
grouped[counts[k]] = []
grouped[counts[k]].append(k)
## Print results
for k, v in sorted(grouped.items()):
for fg in v:
print "%s (%s)" % (fg, counts[fg])
for f in sorted(files[fg]):
print "    %s" % f

这个可以完成所有的拆分、分组和排序工作。在同一个输入文件上运行只花了大约3个"(添加了所有排序内容)。

如果您需要更高的速度,可以尝试使用Cython进行编译,通常速度至少快30%。

更新-Cython

好吧,我刚试过Cython。

只需将上述文件保存为calculate2.pyx即可。在同一文件夹中,创建setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("calculate2", ["calculate2.pyx"])]
)

和一个启动器脚本(我把它命名为calculate2_run.py)

import calculate2
import sys
if __name__ == '__main__':
calculate2.runstuff(sys.stdin)

然后,确保您安装了cython,并运行:

python setup.py build_ext --inplace

这应该会生成一个calculate2.so文件。

现在,像往常一样使用calculate2_run.py(只需通过管道输入find的结果)。

我在没有任何进一步优化的情况下,在同一个输入文件上运行它:这次,它花了1.99''

您可以这样做:

  1. 将初始搜索结果保存在临时文件中
  2. 筛选出文件计数最高的前缀
  3. 在该临时文件中搜索前缀,然后删除该临时文件

find -name 'quest*' | sort -o tempf
target=$(awk -F_ '{print $1}' tempf
| uniq -c | sort -n | tail -1
| sed 's/[0-9]+ //')
grep "$target" tempf
rm -f tempf

注:

  1. 我假设具有相同前缀的文件在相同的子目录中
  2. 输出包含相对于当前目录的路径。如果您只想要基本名称,只需在grep之后执行类似sed 's/.*///'的操作

您的解决方案不是选择文件的基本名称,但我认为您正在寻找:

awk 'NF{ b=$(NF-1); v[b]=v[b] (v[b]?",":"") $NF;  a = ++c[b]} 
a > max {max = a; n=b }  
END {split(v[b],d, ","); for(i in d) print b "_" d[i]}' FS='[/_]'

没有必要对数据进行排序;全分类非常昂贵。

相关内容

  • 没有找到相关文章

最新更新