1

我正在用 Python 为 RawTherapee 编写一个插件。我需要从目录树中可能存在的名为“AboutThisBuild.txt”的文件中提取版本号。尽管 RawTherapee 知道它的安装位置,但这些数据被烘焙到二进制文件中。

我的插件旨在在没有任何命令行参数的情况下收集基本系统数据,以进行短路故障排除。通过获得版本号、修订号和变更集(AKA Mercurial),我可以理清为什么脚本可能无法按预期工作。好的,这就是上下文。

我尝试了多种方法,其中一些建议在本网站的其他地方。主要的是使用 os.walk 和 fnmatch。

问题是速度。搜索整个目录树就像看着油漆变干!

为了减少负载,我试图预测可能的隐藏位置,并且只遍历这些位置。这更快,但具有丢失某些文件的明显缺点。

这就是我目前所拥有的。在 Linux 但尚未在 Windows 上进行测试,因为我仍在研究文件的放置位置。

import fnmatch
import os
import sys

rootPath = ('/usr/share/doc/rawtherapee',
            '~',
            '/media/CoreData/opt/',
            '/opt')
pattern = 'AboutThisBuild.txt'

# Return the first instance of RT found in the paths searched
for CheckPath in rootPath:
    print("\n")
    print(">>>>>>>>>>>>> " + CheckPath)
    print("\n")
    for root, dirs, files in os.walk(CheckPath, True, None, False):
        for filename in fnmatch.filter(files, pattern):
            print( os.path.join(root, filename))
            break

通常,“AboutThisBuild.txt”存储在名为“rawtherapee”的目录/子目录中,或者在目录树中的某处具有字符串。尽管我可以得到 5000 个奇怪的目录名称并在这些目录中搜索“rawtherapee”,然后使用 os.walk 遍历这些目录,但我天真地认为,但我查看过的所有模块和函数(再次)整理目录中的所有文件。

任何人都有更快的搜索整个目录树的方法,还是我坚持使用这种混合选项?

4

3 回答 3

1

我是 Python 的初学者,但我想我知道在 Windows 中查找文件的最简单方法。

import os
for dirpath, subdirs, filenames in os.walk('The directory you wanna search the file in'):
    if 'name of your file with extension' in filenames:
        print(dirpath)

此代码将打印出您在控制台中搜索的文件的目录。您所要做的就是进入目录。

于 2020-03-03T14:25:03.560 回答
0

听起来您在这里需要一个纯 python 解决方案。如果没有,其他答案就足够了。

在这种情况下,您应该使用队列和线程遍历文件夹。虽然有些人可能会说线程永远不是解决方案,但当您受 I/O 限制时,线程是一种很好的加速方式,在这种情况下就是这样。本质上,您将 os.listdir 当前目录。如果它包含您的文件,则像 1999 年那样聚会。如果没有,请将每个子文件夹添加到工作队列中。

如果你很聪明,你可以使用深度优先广度优先遍历来获得最佳结果。

在http://www.tutorialspoint.com/python/python_multithreading.htm有一个很好的例子,我在工作中使用得非常成功。请参阅标题为 的部分Multithreaded Priority Queue。该示例可能会更新为包含线程池,但这不是必需的。

于 2013-11-07T08:00:33.190 回答
0

关于搜索的事情是,你如何到达那里并不重要(例如作弊)。得到结果后,您可以相对快速地验证它是否正确。

您可以通过猜测相当有效地识别候选位置。例如,在 Linux 上,您可以先尝试查看这些位置(显然并非所有位置都是目录,但它不会对os.path.isfile('/;l$/AboutThisBuild.txt').

$ strings /usr/bin/rawtherapee | grep '^/'
/lib/ld-linux.so.2
/H=!
/;l$
/9T$,
/.ba
/usr/share/rawtherapee
/usr/share/doc/rawtherapee
/themes/
/themes/slim
/options
/usr/share/color/icc
/cache
/languages/default
/languages/
/languages
/themes
/batch/queue
/batch/
/dcpprofiles
/@q=
/N6rtexif16NAISOInterpreterE

如果你已经安装了,你可以试试这个locate命令

如果还是没找到,请继续使用蛮力方法

这是strings使用 Python的粗略等价物

>>> from string import printable, whitespace
>>> from itertools import groupby
>>> pathchars = set(printable) - set(whitespace)
>>> with open("/usr/bin/rawtherapee") as fp:
...     data = fp.read()
... 
>>> for k, g in groupby(data, pathchars.__contains__):
...     if not k: continue
...     g = ''.join(g)
...     if len(g) > 3 and g.startswith("/"):
...         print g
... 
/lib64/ld-linux-x86-64.so.2
/^W0Kq[
/pW$<
/3R8
/)wyX
/WUO
/w=H
/t_1
/.badpixH
/d$(
/\$P
/D$Pv
/D$@
/D$(
/l$@
/d$@v?H
/usr/share/rawtherapee
/usr/share/doc/rawtherapee
/themes/
/themes/slim
/options
/usr/share/color/icc
/cache
/languages/default
/languages/
/languages
/themes
/batch/queue.csv
/batch/
/dcpprofiles
/@q=
/N6rtexif16NAISOInterpreterE
于 2013-11-07T05:58:45.400 回答