繁体   English   中英

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

[英]How to print all the files with the same prefix after searching for them?

我需要搜索一个包含许多子目录的目录,每个子目录都包含文件。 这些文件的读法如下Question1234_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 (只需通过管道查找结果即可)。

我在没有任何进一步优化的情况下在同一个输入文件上运行它:这次花了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='[/_]'

无需对数据进行排序; 全分拣非常昂贵。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM