【问题标题】:What is the fastest method of finding a file in Linux and Windows using Python?使用 Python 在 Linux 和 Windows 中查找文件的最快方法是什么?
【发布时间】:2013-11-07 05:46:27
【问题描述】:

我正在用 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 遍历这些目录,但我天真地认为,但我查看过的所有模块和函数(再次)整理目录中的所有文件。

谁有更快的搜索整个目录树的方法,还是我被这个混合选项卡住了?

【问题讨论】:

  • 嗯,为什么不用find?
  • @BurhanKhalid, find 仍然是一个蛮力解决方案。
  • 没错,但它会更快 - 我认为 OP 正在寻找速度而不是技巧。
  • @BurhanKhalid,find 并不是真正的跨平台。我也需要可以在 Windows 上轻松使用的东西。

标签: python linux windows


【解决方案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)

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

【讨论】:

    【解决方案2】:

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

    您可以通过猜测相当有效地识别候选位置。例如,在 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 命令

    如果还是找不到,就继续使用蛮力法

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

    >>> 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
    

    【讨论】:

    • 我上面展示的代码在这个前提下工作。猜测最有可能的目录,然后向下钻取;问题是可用的构建数量。你不能假设构建总是把东西放在同一个地方。我已经要求 RawTherapee 社区指出他们的版本所在的位置,但只有少数人回复了 - link。
    • @SimonCropper,我并不是建议你只使用这个列表。我建议您在您感兴趣的特定二进制文件中搜索看起来像路径的字符串。在 Python 脚本中很容易做到这一点。
    • 我在答案中添加了一个示例。为了彻底,您应该在路径等中允许使用 unicode,但您最终会得到 很多 个更多候选者。
    • 我接受了这个答案,因为它最能反映一个可行的解决方案。实际上,这是对我最初发布的方法的更详细扩展,但 gnibbler 提出了一个我打算实施的好主意——从已发布的构建中提取路径并在我的主要搜索中使用这些路径。
    • 我原来的问题“使用 Python 在 Linux 和 Windows 中查找文件的最快方法是什么?”实际上仍然是开放的。一旦主搜索完成后退回到搜索整个文件系统是不现实的,因为它需要的时间太长。我想我会在我的日志中声明“无法确定”,并将确定 RT 版本的义务推给用户。
    【解决方案3】:

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

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

    如果你够聪明,你可以玩depth first vs breadth first 遍历以获得最佳结果。

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

    【讨论】:

    • 线程是一个糟糕的主意,如果这意味着您将在您的(机械)硬盘驱动器上寻找(抖动)。如果是 SSD,几个线程可能会有所帮助
    • @VooDooNOFX,是的,我确实需要一个纯 Python 解决方案。真正跨平台的东西,适用于 Python 2.7 和 3.0。多线程听起来确实很有趣,但正如 gnibbler 所说,这将导致 2 或 3 个进程争夺对 HD 的控制权,从而导致整个媒体中潜在的不稳定搜索。这可能会导致脚本花费的时间比使用单个进程系统地遍历树的时间要长。
    猜你喜欢
    • 2016-05-14
    • 2013-10-24
    • 1970-01-01
    • 2019-07-18
    • 2010-10-13
    • 2021-07-17
    • 2011-02-01
    • 2015-06-07
    • 2011-10-04
    相关资源
    最近更新 更多