Python递归文件系统搜索功能

时间:2013-10-05 00:07:06

标签: python recursion filesystems

我是这个网站的新手,对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之外的任何内容。

3 个答案:

答案 0 :(得分: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

修复此问题后,您也遇到了一个小问题。如果到达正确的目录,然后在找到文件之前找到所有子目录,则会将fullPath重新分配给None,以便os.path.join(fullPath, file)失败。无论如何,您都希望从函数的开头使用原始值。

幸运的是,您已在path中拥有该原始版本。而且,一旦你使用它,你不需要fullPath任何东西,所以你可能只是废弃它。

答案 1 :(得分:3)

为什么不os.walk()http://docs.python.org/2/library/os.html#os.walk可能会做你想要的大部分。

答案 2 :(得分:0)

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

from glob import glob
print glob("**/filename")