如何避免从 os.walk 获取重复路径

How can I avoid getting duplicate paths from os.walk

我有以下目录结构

/mnt/type/split/v2/doc/RESOURCE_ID/YYYY/FY/DOCUMENT_ID

例如,一条路径可能是

/mnt/type/split/v2/doc/100045/2008/FY/28

其中

RESOURCE_ID = 100045
YYYY = 2008
DOCUMENT_ID = 28

注意,DOCUMENT_ID是路径中的最后一个目录——DOCUMENT_ID目录下会有文件

我试图使用以下代码清点此结构

def survey():
    magic_paths = []
    for (resource_id, dirname,filename) in os.walk('/mnt/type/split/v2/doc'):
        if resource_id:
            for (magic_path, dirname2,filename2) in os.walk(resource_id):
                 if len(magic_path.split(os.sep)) == 10:
                      magic_paths.append(magic_path + os.linesep)
    write_survey(magic_paths)
    x = len(magic_paths)
    return x

我的 magic_paths 列表中的每个路径都有五个副本。我有 1,500,000 条路径,所以我的列表中有 7,500,00 个项目。

前 1,500,000 个是唯一值。接下来的 6,000,000 个由以 RESOURCE_ID 为根的组组成,重复 4 次

/mnt/type/split/v2/doc/100045/2008/FY/28 #obs_1
/mnt/type/split/v2/doc/100045/2008/FY/29 #obs_2
/mnt/type/split/v2/doc/100045/2008/FY/30 #obs_3
/mnt/type/split/v2/doc/100045/2008/FY/31 #obs_4
/mnt/type/split/v2/doc/1028/2008/FY/28   #obs_5 # see the new RESOURCE_ID
.
.   1,499,995 more unique values
.
/mnt/type/split/v2/doc/100045/2008/FY/28 #begin of first repetition
/mnt/type/split/v2/doc/100045/2008/FY/29
/mnt/type/split/v2/doc/100045/2008/FY/30
/mnt/type/split/v2/doc/100045/2008/FY/31
/mnt/type/split/v2/doc/100045/2008/FY/28 #begin of second repetition
/mnt/type/split/v2/doc/100045/2008/FY/29
/mnt/type/split/v2/doc/100045/2008/FY/30
/mnt/type/split/v2/doc/100045/2008/FY/31
/mnt/type/split/v2/doc/100045/2008/FY/28 #begin of third repetition
/mnt/type/split/v2/doc/100045/2008/FY/29
/mnt/type/split/v2/doc/100045/2008/FY/30
/mnt/type/split/v2/doc/100045/2008/FY/31
/mnt/type/split/v2/doc/100045/2008/FY/28 #begin of fourth repetition
/mnt/type/split/v2/doc/100045/2008/FY/29
/mnt/type/split/v2/doc/100045/2008/FY/30
/mnt/type/split/v2/doc/100045/2008/FY/31
/mnt/type/split/v2/doc/1028/2008/FY/28     #series of 4 repetitions based on RESOURCE ID 1028 

每个级别的目录和子目录中都有各种文件,我只需要清点 DOCUMENT_ID 的路径即可。

我不明白为什么结果是这样的。我相信我是从 RESOURCE_ID 开始的,并且只找到深度为 9 的目录,因为在 os.sep 上拆分给我一个包含十个项目的列表。

'/mnt/type/split/v2/doc/100045/2008/FY/31'.split(os.sep) = ['','mnt',type','split','v2','doc','100045','2008','FY','31']

回复评论中的问题

  1. 我相信我正在获取每个 RESOURCE_ID 目录,然后遍历它。从第一个 os.walk 返回的其他项目(目录名和文件名)将被忽略
  2. 我认为 os.listdir 行不通,我可以使用 glob 进行此操作,但担心它会占用我的内存

os.walk()递归地 遍历目录结构。对于您遇到的每个目录,您开始 另一个递归调用 。因此,对于每个目录,您递归地遍历该目录以及所有嵌套目录。这包括嵌套目录。通过开始搜索 /mnt/type/split/v2/doc/mnt/type/split/v2/doc/100045/mnt/type/split/v2/doc/100045/2008/mnt/type/split/v2/doc/100045/2008/mnt/type/split/v2/doc/100045/2008/FY 路径,您可以为每个文档 ID 生成 5 个匹配项。

只需调用 os.walk() 一次:

def survey():
    magic_paths = []
    for (resource_id, dirnames, filenames) in os.walk('/mnt/type/split/v2/doc'):
         if len(resource_id.split(os.sep)) == 10:
              magic_paths.append(resource_id + os.linesep)
    write_survey(magic_paths)
    x = len(magic_paths)
    return x

您可能想在找到匹配项后删减搜索;找到 DOCUMENT_ID 目录后,再搜索更多子目录就没有意义了:

def survey():
    magic_paths = []
    for (resource_id, dirnames, filenames) in os.walk('/mnt/type/split/v2/doc'):
         if len(resource_id.split(os.sep)) == 10:
              magic_paths.append(resource_id + os.linesep)
              dirnames[:] = []  # clear the subdirs list to stop further recursion here
    write_survey(magic_paths)
    x = len(magic_paths)
    return x