我正在编写一个脚本,以递归地遍历主文件夹中的子文件夹,并构建一个特定文件类型的列表。我对剧本有点意见。目前设置如下:

for root, subFolder, files in os.walk(PATH):
    for item in files:
        if item.endswith(".txt") :
            fileNamePath = str(os.path.join(root,subFolder,item))

问题是subFolder变量拉入的是子文件夹列表,而不是ITEM文件所在的文件夹。我在考虑之前运行子文件夹的for循环,并加入路径的第一部分,但我想我会仔细检查,看看是否有人有任何建议之前。


当前回答

您最初的解决方案几乎是正确的,但是变量“root”在递归遍历时被动态更新。Os.walk()是一个递归生成器。每个元组(root, subFolder, files)都是针对特定的根目录设置的。

i.e.

root = 'C:\\'
subFolder = ['Users', 'ProgramFiles', 'ProgramFiles (x86)', 'Windows', ...]
files = ['foo1.txt', 'foo2.txt', 'foo3.txt', ...]

root = 'C:\\Users\\'
subFolder = ['UserAccount1', 'UserAccount2', ...]
files = ['bar1.txt', 'bar2.txt', 'bar3.txt', ...]

...

我对你的代码做了轻微的调整,以打印一个完整的列表。

import os
for root, subFolder, files in os.walk(PATH):
    for item in files:
        if item.endswith(".txt") :
            fileNamePath = str(os.path.join(root,item))
            print(fileNamePath)

希望这能有所帮助!

编辑:(根据反馈)

OP误解/错误标记了子文件夹变量,因为它实际上是“根”中的所有子文件夹。因为OP,你要执行os。path。Join (str, list, str),这可能不像你预期的那样。

为了帮助增加清晰度,你可以试试这个标签方案:

import os
for current_dir_path, current_subdirs, current_files in os.walk(RECURSIVE_ROOT):
    for aFile in current_files:
        if aFile.endswith(".txt") :
            txt_file_path = str(os.path.join(current_dir_path, aFile))
            print(txt_file_path)

其他回答

您可以通过这种方式返回绝对路径文件的列表。

def list_files_recursive(path):
    """
    Function that receives as a parameter a directory path
    :return list_: File List and Its Absolute Paths
    """

    import os

    files = []

    # r = root, d = directories, f = files
    for r, d, f in os.walk(path):
        for file in f:
            files.append(os.path.join(r, file))

    lst = [file for file in files]
    return lst


if __name__ == '__main__':

    result = list_files_recursive('/tmp')
    print(result)

我将把John La Rooy的列表理解转换为嵌套for,以防其他人理解它有困难。

result = [y for x in os.walk(PATH) for y in glob(os.path.join(x[0], '*.txt'))]

应该相当于:

import glob
import os

result = []

for x in os.walk(PATH):
    for y in glob.glob(os.path.join(x[0], '*.txt')):
        result.append(y)

下面是列表理解和函数os的文档。走着走着。

如果你不介意安装一个额外的灯光库,你可以这样做:

pip install plazy

用法:

import plazy

txt_filter = lambda x : True if x.endswith('.txt') else False
files = plazy.list_files(root='data', filter_func=txt_filter, is_include_root=True)

结果应该是这样的:

['data/a.txt', 'data/b.txt', 'data/sub_dir/c.txt']

它可以在Python 2.7和Python 3上运行。

Github: https://github.com/kyzas/plazy文件

免责声明:我是plazy的作者。

新的pathlib库将其简化为一行:

from pathlib import Path
result = list(Path(PATH).glob('**/*.txt'))

你也可以使用生成器版本:

from pathlib import Path
for file in Path(PATH).glob('**/*.txt'):
    pass

这将返回Path对象,您可以将其用于几乎任何事情,或者通过file.name获取文件名作为字符串。

此函数将递归地将文件放入列表中。

import os


def ls_files(dir):
    files = list()
    for item in os.listdir(dir):
        abspath = os.path.join(dir, item)
        try:
            if os.path.isdir(abspath):
                files = files + ls_files(abspath)
            else:
                files.append(abspath)
        except FileNotFoundError as err:
            print('invalid directory\n', 'Error: ', err)
    return files