在目录列表中查找第一次出现的文件

时间:2014-06-08 17:54:43

标签: python

我有一个目录列表。在此列表中,我想找到具有特定文件的第一个目录,并返回该文件的abspath。我目前有以下代码可用:

from os.path import exists, join, abspath

path = ["/some/where", "/some/where/else", "/another/location"]
file_name = "foo.bar"
try:
    file = [abspath(join(d, file_name)) for d in path if exists(join(d, file_name))][0]
except IndexError:
    file = ""

我怎样才能更优雅?我特别不喜欢的是两个连接。

2 个答案:

答案 0 :(得分:1)

您可以将join拉出到genexp:

>>> paths = ["/some/where", "/some/where/else", "/another/location", "/tmp"]
>>> file_name = "foo.bar"
>>> joined = (join(p, file_name) for p in paths)
>>> next((abspath(f) for f in joined if exists(f)), '')
'/tmp/foo.bar'

(如果你想通过内联它,你可以简单地将它作为一个单行。)

请注意,这与您的代码不同,因为它在找到第一个代码后停止,而您的代码会找到所有代码。

答案 1 :(得分:0)

即使你事先加入了带有文件名的目录以避免加入两次,你仍然可以加入所有目录。例如,如果您的列表有10个目录,则将调用os.path.join() 10次,即使包含该文件的目录可能位于列表中的第一个。更糟糕的是,当你不得不做几千或几百万次时,它就会增加。

我看不到任何使用列表理解的优雅解决方案,所以我设计了一个迭代的解决方案。在我的解决方案中,一旦我们找到包含该文件的目录,我们立即返回该文件的完整绝对路径,并且不再进一步处理。这个解决方案并不优雅,但速度更快。

此解决方案的缺点是调用函数的开销。如果您找到的是在列表的末尾,我的解决方案可能比列表推导解决方案慢。

import os

def find_first(directories, filename):
    '''
    Given a list of directories and a file name, find first existent
    occurrence.
    '''
    for directory in directories:
        fullpath = os.path.abspath(os.path.join(directory, filename))
        if os.path.exists(fullpath):
            return fullpath
    return False

directories = ['/foo', '/bin', '/usr/bin']
filename = 'bash'
print find_first(directories, filename) # /bin/bash