Python递归读取目录

1 投票
1 回答
2463 浏览
提问于 2025-04-17 08:35

我想避免使用os.walk,我正在用一个递归函数来读取文件和文件夹,并把文件存储到一个字典里。

我去掉了os.chdir这个部分,但不知道为什么,现在这个函数把路径和文件名也拼在一起了,导致出现了错误:WindowsError: [Error 267] 目录名无效:'c:\data\foo\notes\*.*'。它在读取文件夹foo的时候,把路径和foo还有文件notes.txt拼在了一起,而不是应该是foo加上libary文件夹。

1 个回答

2

这对我来说似乎是有效的

import os

op = os.path

def fileRead(mydir):
    data = {}
    root = set()
    for i in os.listdir(mydir):
        path = op.join(mydir, i)
        print(path)
        if op.isfile(path):
            data.setdefault(i, set())
            root.add(op.relpath(mydir).replace("\\", "/"))
            data[i] = root
        else:
            data.update(fileRead(path))
    return data


d = fileRead("c:\python32\programas")
print(d)

不过我还是不太明白你为什么要使用设置根目录。我觉得这样做的目的是为了在两个目录中有相同文件时,能够保留所有的目录。但是这样并不奏效:每次更新都会删除重复键(文件名)的存储值。

这里有一段可以正常工作的代码,使用了一个叫做defaultdict的东西。你也可以用普通的字典(就像你的代码那样),但用defaultdict的话,你就不需要在使用某个键之前检查它是否已经初始化:

import os
from collections import defaultdict
op = os.path

def fileRead(mydir):
    data = defaultdict(list)
    for i in os.listdir(mydir):
        path = op.join(mydir, i)
        print(path)
        if op.isfile(path):
            root = op.relpath(mydir).replace("\\", "/")
            data[i].append(root)
        else:
            for k, v in fileRead(path).items():
                data[k].extend(v)
    return data


d = fileRead("c:\python32\programas")
print(d)

补充:关于@hughdbrown的评论:

如果你用data.update(fileRead(path).items())来更新数据,当我在我的电脑上调用fileRead("c:/python26/programas/pack")时(现在在py26环境下):

c:/python26/programas/pack\copia.py
c:/python26/programas/pack\in pack.py
c:/python26/programas/pack\pack2
c:/python26/programas/pack\pack2\copia.py
c:/python26/programas/pack\pack2\in_pack2.py
c:/python26/programas/pack\pack2\pack3
c:/python26/programas/pack\pack2\pack3\copia.py
c:/python26/programas/pack\pack2\pack3\in3.py

defaultdict( 'list'>, {'in3.py': ['pack/pack2/pack3'], 'copia.py': ['pack/pack2/pack3'],
'in pack.py': ['pack'], 'in_pack2.py': ['pack/pack2']})

注意,在多个目录中重复的文件(比如copia.py)只会显示其中一个目录,通常是最深的那个。不过,当你使用以下代码时,所有的目录都会列出:

for k, v in fileRead(path).items():  data[k].extend(v)

c:/python26/programas/pack\copia.py
c:/python26/programas/pack\in pack.py
c:/python26/programas/pack\pack2
c:/python26/programas/pack\pack2\copia.py
c:/python26/programas/pack\pack2\in_pack2.py
c:/python26/programas/pack\pack2\pack3
c:/python26/programas/pack\pack2\pack3\copia.py
c:/python26/programas/pack\pack2\pack3\in3.py

defaultdict(, {'in3.py': ['pack/pack2/pack3'], 'copia.py': ['pack', 'pack/pack2', 'pack/pack2/pack3'],
'in pack.py': ['pack'], 'in_pack2.py': ['pack/pack2']})

撰写回答