使用os.walk()递归搜索多个目录

时间:2016-04-20 21:30:18

标签: python-2.7 os.walk

我正在尝试浏览目录并递归搜索父目录中的三个子目录。这将有效:

def find_files(fPattern, list_to_append):
    for root, dirnames, filenames in os.walk(r'c:\workspace\Sandbar_Process\csv_output\CSVs'):
        for filename in fnmatch.filter(filenames, fPattern):
            list_to_append.append(os.path.join(root, filename))
    for root, dirnames, filenames in os.walk(r'c:\workspace\Sandbar_Process\csv_output\No_Bath_CSVS'):
        for filename in fnmatch.filter(filenames, fPattern):
            list_to_append.append(os.path.join(root, filename))
    for root, dirnames, filenames in os.walk(r'c:\workspace\Sandbar_Process\csv_output\Two_Bar_CSVS'):
        for filename in fnmatch.filter(filenames, fPattern):
            list_to_append.append(os.path.join(root, filename))  
    return list_to_append

但它相当笨重。我如何os.walk通过多个子目录而不必硬编码?

1 个答案:

答案 0 :(得分:0)

如果你只有r'c:\workspace\Sandbar_Process\csv_output'中的那3个文件夹,你可以从该文件夹中删除,否则你可以在你的第一次迭代中删除额外的文件夹,就像这样

案例1,没有额外的文件夹

for root, dirnames, filenames in os.walk(r'c:\workspace\Sandbar_Process\csv_output'):
    for filename in fnmatch.filter(filenames, fPattern):
        list_to_append.append(os.path.join(root, filename))    

案例2,额外文件夹

my_folders = ['CSVs', 'No_Bath_CSVS', 'Two_Bar_CSVS']
first = True
for root, dirnames, filenames in os.walk(r'c:\workspace\Sandbar_Process\csv_output'):
    if first:
        dirnames.clear()
        dirnames.extend(my_folders)
        first = False
    for filename in fnmatch.filter(filenames, fPattern):
        list_to_append.append(os.path.join(root, filename)) 
通过os.walkdirnames收益率的操作会影响您稍后访问子文件夹的方式

查看文档中有关它的内容

  

os.walk(top, topdown=True, onerror=None, followlinks=False)

     

topdown True时,调用者可以就地修改 dirnames 列表(可能使用del或slice赋值),{{1}只会递归到名称保留在 dirnames 中的子目录中;这可用于修剪搜索,强制执行特定的访问顺序,甚至可以通知walk()有关调用者在再次恢复walk()之前创建或重命名的目录。在topdown为walk()时修改 dirnames 对walk的行为没有影响,因为在自下而上模式中, dirnames 中的目录是在dirpath本身之前生成的生成。

您也可以像这样重新定义您的功能

False

在这里,您将要使用的文件夹提供给您的功能,然后您只需要使用所需的文件夹进行调用,或者定义另一个使用这些文件夹调用此文件夹的功能,这样您就不会重复代码没有必要。

另外,如果你总是在该文件夹中工作,你可以把它放在像这样的全局变量

def find_files(fPattern, list_to_append, path):
    for root, dirnames, filenames in os.walk(path):
        for filename in fnmatch.filter(filenames, fPattern):
            list_to_append.append(os.path.join(root, filename))  
    return list_to_append

并且仅提供相对于该文件夹的文件夹名称,并且当您需要绝对路径来执行某些操作时

WORKING_FOLDER = r'c:\workspace\Sandbar_Process\csv_output'

并定义一个这样的函数,例如

os.path.join(WORKING_FOLDER, foldername)

,例如将其称为

def my_work_in(fPattern, list_to_append, folders):
    result = list_to_append
    for foldername in folders:
        result = find_files(fPattern, result , os.path.join(WORKING_FOLDER, foldername))
    return result

当然你应该知道修改你给你的功能的东西通常是不好的做法,所以你的功能应该是

result = my_work_in(fPattern, [],  ['CSVs', 'No_Bath_CSVS', 'Two_Bar_CSVS'] )

或更好作为发电机

def find_files(fPattern, path):
    result = []
    for root, dirnames, filenames in os.walk(path):
        for filename in fnmatch.filter(filenames, fPattern):
            result.append(os.path.join(root, filename))  
    return list_to_append

在这两种情况下都没有不必要的修改,您可以将其用作

def find_files(fPattern, path):
    for root, dirnames, filenames in os.walk(path):
        for filename in fnmatch.filter(filenames, fPattern):
            yield os.path.join(root, filename)

为此,生成器版本更好,因为您不会丢失具有中间结果的内存