在非常大的目录中搜索名称中包含文本的文件

Search a very large directory for a file containing text in it's name

提问人:Just Works 提问时间:1/10/2023 最后编辑:Just Works 更新时间:2/7/2023 访问量:76

问:

我有一个网络共享,其中包含大约 300,000 个文件,并且它不断变化(添加和删除文件)。我想在目录中搜索特定文本以查找此目录中的某些文件。我已经尽可能地削减了我的方法,但仍然需要 6 分钟以上才能完成。我可能可以在同一时间手动完成,具体取决于我正在搜索的字符串数量。我想多线程或多处理它,但我不确定如何在一次调用中完成:即

for filename in os.scandir(sourcedir).

谁能帮我解决这个问题?

def scan(sourcedir:str, oset:set[str]|str) -> set[str]:
    found = set()
        for filename in os.scandir(sourcedir):
            for ordr in oset:
                if ordr in filename.name:
                    print(filename.name)
                    found.add(filename.name)
                    break

典型调用的结果: 在 395.033 秒内调用 516 次函数

排序方式:标准名称

ncalls tottime percall cumtime percall 文件名:lineno(函数) 6 0.000 0.000 0.003 0.000 :39(ISDIR) 6 0.000 0.000 1.346 0.224 :94(同文件) 12 0.000 0.000 0.001 0.000 :103(加入) 30 0.000 0.000 0.000 0.000 :150(分体驱动) 6 0.000 0.000 0.000 0.000 :206(拆分) 6 0.000 0.000 0.000 0.000 :240(基本名称) 6 0.000 0.000 0.000 0.000 :35(_get_bothseps) 1 0.000 0.000 0.000 0.000 :545(标准路径) 1 0.000 0.000 0.000 0.000 :577(abspath) 1 0.000 0.000 395.033 395.033 :1() 1 0.000 0.000 395.033 395.033 CopyOrders.py:31(主) 1 389.826 389.826 389.976 389.976 CopyOrders.py:67(扫描) 1 0.000 0.000 5.056 5.056 CopyOrders.py:88(复制) 1 0.000 0.000 0.000 0.000 getopt.py:56(getopt) 6 0.000 0.000 0.001 0.000 shutil.py:170(_copyfileobj_readinto) 6 0.000 0.000 1.346 0.224 shutil.py:202(_samefile) 18 0.000 0.000 1.493 0.083 shutil.py:220(_stat) 6 0.001 0.000 4.295 0.716 shutil.py:226(复制文件) 6 0.000 0.000 0.756 0.126 shutil.py:290(复制模式) 6 0.000 0.000 5.054 0.842 shutil.py:405(复印) 6 0.000 0.000 0.000 0.000 {內用方法_stat。S_IMODE} 6 0.000 0.000 0.000 0.000 {內用方法_stat。S_ISDIR} 6 0.000 0.000 0.000 0.000 {內用方法_stat。S_ISFIFO} 1 0.000 0.000 395.033 395.033 {內置方法 builtins.exec} 6 0.000 0.000 0.000 0.000 {內置方法 builtins.hasattr} 73 0.000 0.000 0.000 0.000 {內置方法 builtins.isinstance} 38 0.000 0.000 0.000 0.000 {內置方法 builtins.len} 6 0.000 0.000 0.000 0.000 {內置方法 builtins.min} 14 0.003 0.000 0.003 0.000 {內置方法 builtins.print} 12 2.180 0.182 2.180 0.182 {內置方法 io.open} 1 0.000 0.000 0.000 0.000 {內入方法nt._getfullpathname} 1 0.000 0.000 0.000 0.000 {內入方法nt._path_normpath} 6 0.012 0.002 0.012 0.002 {內入方法 nt.chmod} 49 0.000 0.000 0.000 0.000 {內置方法 nt.fspath} 1 0.149 0.149 0.149 0.149 {內置方法 nt.scandir} 36 2.841 0.079 2.841 0.079 {內入方法 nt.stat} 12 0.000 0.000 0.000 0.000 {內置方法 sys.audit} 12 0.019 0.002 0.019 0.002 {'_io._IOBase' 对象的方法'exit'} 6 0.000 0.000 0.000 0.000 {“memoryview”对象的方法“exit”} 6 0.000 0.000 0.000 0.000 {“设置”对象的方法“add”} 1 0.000 0.000 0.000 0.000 {方法 'disable' of '_lsprof.探查器对象} 36 0.000 0.000 0.000 0.000 {'str' 对象的方法 'find'} 12 0.001 0.000 0.001 0.000 {'_io.BufferedReader 的对象} 30 0.000 0.000 0.000 0.000 {“str”对象的“替换”方法} 6 0.000 0.000 0.000 0.000 {“str”对象的“rstrip”方法} 6 0.000 0.000 0.000 0.000 {'_io 的 'write' 方法。BufferedWriter 的对象}

python-3.x 线程 IO 多处理

评论


答:

0赞 Kaleb Fenley 1/10/2023 #1

你可以试试 glob

我没有一个包含 300,000 个文件的目录来测试它,但我假设它会很快(几秒钟)。

import glob

sourcedir = r'path\to\your\files'
oset = ['some','list','not','shown','in','your','code']

found = []
for ordr in oset:
# Get a list of all files in the "sourcedir" directory with "ordr" in the filename
    files = [f for f in glob.glob(f"{sourcedir}\*{ordr}*")]
    found.extend(files)

print('\n'.join(found))

评论

0赞 Just Works 1/11/2023
从我看到的比较运行通话所需时间的消息来源来看,glob 比其他的慢。我想它值得测试。
3赞 blhsing 1/10/2023 #2

由于您只对文件名感兴趣,而对任何其他文件属性不感兴趣,因此不应使用文件来产生具有所有文件属性的构建对象的开销。请改用以仅检索文件名列表。os.scandiros.listdir

其次,您可以使用交替模式的正则表达式来更有效地搜索多个子字符串,因为该模块是用速度快得多的 C 语言编写的。re

import re

def scan(sourcedir:str, oset:set[str]) -> set[str]:
    regex = re.compile('|'.join(map(re.escape, oset)))
    return set(filter(regex.search, os.listdir(sourcedir)))

请注意,参数类型为 ,这没什么意义,因为字符串和字符串的容器无法以一致的方式处理。我已经把它打成在我的例子中。osetset[str]|strset[str]

评论

0赞 Just Works 1/11/2023
我会再试一次,但在我的测试中,listdir 比 scandir 慢一点。我添加了“|str”以停止显示愚蠢的pylint错误,指出set[str]与set[str]|str不兼容。这显然没有意义,但是......皮林特。我说得对吗?我以前没有尝试过,我对此持开放态度,但大部分时间都花在从网络共享中获取文件列表上,所以这就是我一直关注的重点。
0赞 Just Works 2/7/2023 #3

我最终发现,无论我扫描多少个文件,它只需要一个较短的文件列表(很多)。因此,我认为收集要比较的现有文件列表所花费的很长时间类似于索引目录。我正在将该工具用于更大的文件集。对于 onsies 和 twosies,我手动搜索。我想就是这样。

评论

0赞 Community 2/9/2023
您的答案可以通过其他支持信息进行改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。