如何递归地遍历所有子目录并读取文件?

34

我有一个根目录,其中包含多个子目录,所有子目录都包含名为data.txt的文件。我想编写一个脚本,接收“根”目录,然后遍历所有子目录并读取每个子目录中的“data.txt”,然后将每个data.txt文件中的内容写入输出文件。

这是我的一部分代码:

import os
import sys
rootdir = sys.argv[1]

with open('output.txt','w') as fout:
    for root, subFolders, files in os.walk(rootdir):
        for file in files:
            if (file == 'data.txt'):
                #print file
                with open(file,'r') as fin:
                    for lines in fin:
                        dosomething()

我的dosomething()部分 - 我已经测试并确认了它可以正常工作,如果我只对一个文件运行该部分。我还确认,如果我让它打印文件而不是执行部分内容(注释掉的那一行),脚本会打印出 "data.txt"。

现在,如果我运行它,Python会给我这个错误:

File "recursive.py", line 11, in <module>
    with open(file,'r') as fin:
IOError: [Errno 2] No such file or directory: 'data.txt'

我不确定为什么找不到它 -- 毕竟,如果我取消注释'print file'行,它会打印出data.txt。我做错了什么?


1
只是一个风格注释:一旦嵌套这么深,阅读起来可能会很困难。为了简化,我会将内部部分放在单独的 def do_file(filename): ... 函数中。你也可以使用 if file == 'data.txt': continue 来简化并节省一个级别。另请参见 PEP 20:“扁平比嵌套好”。 - Ben Hoyt
2个回答

55

你需要使用绝对路径,你的file变量只是一个没有目录路径的本地文件名。而root变量则是该路径:

你需要使用绝对路径,你的file变量只是一个没有目录路径的本地文件名。而root变量则是该路径:

with open('output.txt','w') as fout:
    for root, subFolders, files in os.walk(rootdir):
        if 'data.txt' in files:
            with open(os.path.join(root, 'data.txt'), 'r') as fin:
                for lines in fin:
                    dosomething()

7
如果像我一样,读者希望在迭代文件名时进行额外的筛选,那么这个问题的答案会非常有帮助:https://dev59.com/lHI95IYBdhLWcg3wtwVe - BigglesZX
2
os.walk() + follow symlinks 解决了如何跟随链接的问题。 - Schorsch

0
[os.path.join(dirpath, filename) for dirpath, dirnames, filenames in os.walk(rootdir) 
                                 for filename in filenames]

使用函数式编程方法可以使得获取树形结构的代码更加简洁、清晰和符合 Python 风格。

你可以将 os.path.join(dirpath, filename) 包装在任何函数中,以处理所获取的文件或保存路径数组以供进一步处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接