6

我需要遍历一个可能非常大的目录(任意大)。据我了解,常规glob.glob函数将所有匹配文件名的列表存储在内存中,但该glob.iglob函数使用迭代器。所以使用常规glob.glob函数是不可能的,因为目录中可能有很多文件。

我的问题是以iglob看似随机的顺序遍历目录。我希望它按字母顺序遍历文件。我不能一次得到所有文件名的列表,只是对它们进行排序,所以我想知道是否有一种方法可以iglob按字母顺序遍历目录。

4

2 回答 2

8

不,没有,没有将目录的所有内容读入内存。操作系统按目录顺序提供文件名,如果要对它们进行排序,还需要将内容全部读入内存。

您可以在匹配的文件之后对结果进行排序,前提是该集合足够小以通过调用输出来iglob()放入内存:sorted()iglob()

for filename in sorted(iglob(path)):

请注意,当不递归到子目录时,iglob()已经将单个目录的所有条目加载到列表中(部分原因是fnmatch()返回一个列表)。

于 2012-11-11T22:02:36.147 回答
2

glob模块的文档中:

glob模块根据 Unix shell 使用的规则查找与指定模式匹配的所有路径名。不进行波浪号扩展,但*, ?, 和用 表示的字符范围[]将被正确匹配。这是通过协同使用os.listdir()and fnmatch.fnmatch()函数来完成的,而不是通过实际调用子 shell 来完成。

如果我们查看文档os.listdir

os.listdir(路径)

返回一个列表,其中包含路径给定的目录中条目的名称。 该列表是任意顺序的。它不包括特殊条目“。” 和 '..' 即使它们存在于目录中。

所以glob.glob不按字母顺序返回文件。文档中的任何地方都没有说明。依赖这种行为是一个错误。如果你想要一个有序的序列,你必须对结果进行排序。然后你可以很容易地想象没有办法iglob返回一个排序的结果,因为它甚至没有所有可用的结果。

如果内存真的是个问题,那么您有两种选择:

  1. 放弃“aplhabetical order”要求,只需使用iglob.
  2. 使用某种“桶排序”对数据进行排序,将大部分数据保存在磁盘上并将其分块加载到 RAM 中(这些技术在计算机编程艺术第 3 册中进行了解释)。这种方法会使您的程序变慢并且可能更难编写。但是,如果您真的不能将所有文件名保存在 RAM 中,那么您最终将不得不将它们保存在磁盘上。
于 2012-11-11T22:04:23.433 回答