0

我是这个网站的新手,对 Python 也比较陌生。我目前正在做一个项目,该项目需要我编写一个递归搜索函数来查看文件和目录。该函数采用目录路径和搜索条件,在本例中为文件名,并且应该返回文件的完整路径,前提是它存在。

def search(path, file):
fullPath = path
inDir = os.listdir(path)

for element in inDir:
    if os.path.join(path, file) == os.path.join(path, element):
        fullPath = os.path.join(fullPath, file)
        print(fullPath)
        return fullPath
    elif os.path.isdir(os.path.join(path, element)):
        fullPath = search(os.path.join(path, element), file)

我知道 Python 中的递归需要递归调用的 return 语句,但我也尝试过:

def search(path, file):
fullPath = path
inDir = os.listdir(path)

for element in inDir:
    if os.path.join(path, file) == os.path.join(path, element):
        fullPath = os.path.join(fullPath, file)
        print(fullPath)
        return fullPath
    elif os.path.isdir(os.path.join(path, element)):
        return search(os.path.join(path, element), file)

和其他几种变体,但无济于事。第一个函数打印正确的路径,所以我知道递归中的某个点fullPath包含正确的路径,但我似乎无法让函数返回除None.

4

3 回答 3

3

让我们看看你的代码:

for element in inDir:
    if os.path.join(path, file) == os.path.join(path, element):
        fullPath = os.path.join(fullPath, file)
        print(fullPath)
        return fullPath
    elif os.path.isdir(os.path.join(path, element)):
        return search(os.path.join(path, element), file)

它一一浏览文件。当您第一次找到匹配的文件时,您会返回它——这很好。

但是当你第一次找到任何目录时,你只是搜索那个目录并返回结果——这很糟糕。

如果您通过整个目录而没有找到匹配项或子目录,则您会脱离函数的末尾,这意味着您返回None.

所以,想象一下这个结构:

root/
    sub1/
        sub1a/
            notthefile
    sub2/
        thefile

你开始浏览root。因为sub1是目录,所以返回搜索的结果sub1。因为sub1a是目录,所以返回搜索的结果sub1a。因为sub1a没有任何目录或任何匹配的文件,所以您返回None.


那么,你怎么能解决这个问题呢?很简单:如果递归搜索失败,不要只返回它的值,继续循环:

elif os.path.isdir(os.path.join(path, element)):
    fullpath = search(os.path.join(path, element), file)
    if fullpath is not None:
        return fullpath

一旦你解决了这个问题,你也会遇到一个小问题。如果您找到正确的目录,然后在找到文件之前找到任何子目录,您将重新分配fullPathNone,因此os.path.join(fullPath, file)将失败。无论如何,您都想从函数的开始使用原始值。

幸运的是,您已经拥有原始版本,在path. 而且,一旦你使用它,你就不需要fullPath任何东西了,所以你还不如废弃它。

于 2013-10-05T00:16:28.513 回答
3

为什么不 os.walk() http://docs.python.org/2/library/os.html#os.walk可能会满足您的大部分需求。

于 2013-10-05T01:24:06.203 回答
1

对于完全不同的东西,但不是可扩展的。尝试全局

from glob import glob
print glob("**/filename")
于 2013-10-05T04:10:53.787 回答