Os.walk 迭代以什么顺序进行迭代?

我关心的是 os.walk()给出的文件和目录的顺序。如果我有这些目录,11011122202122310,11,12,输出列表的顺序是什么?

是否按数值排序?

1 2 3 10 20 30 11 21 31 12 22 32

或者按 ASCII 值排序,就像 ls给出的那样?

1 10 11 12 2 20 21 22 3 30 31 32

另外,如何获得特定的排序?

67687 次浏览

os.walk使用 os.listdir。下面是 os.listdir的 docstring:

Listdir (path)-> list _ of _ string

返回一个包含目录中条目名称的列表。

path: path of directory to list

列表按任意顺序 排列 条目’.’和’. .’即使它们出现在目录中。

(我的强调)。

但是,您可以使用 sort来确保所需的顺序。

for root, dirs, files in os.walk(path):
for dirname in sorted(dirs):
print(dirname)

(请注意,dirname 是字符串而不是 int,因此 sorted(dirs)将它们排序为字符串——这一次是可取的。

正如 Alfe 和 Ciro Santilli 指出的,如果希望目录按排序顺序为 递归的,那么修改 dirs 就位:

for root, dirs, files in os.walk(path):
dirs.sort()
for dirname in dirs:
print(os.path.join(root, dirname))

你可以自己测试一下:

import os


os.chdir('/tmp/tmp')
for dirname in '1 10 11 12 2 20 21 22 3 30 31 32'.split():
try:
os.makedirs(dirname)
except OSError: pass




for root, dirs, files in os.walk('.'):
for dirname in sorted(dirs):
print(dirname)

指纹

1
10
11
12
2
20
21
22
3
30
31
32

如果要按数字顺序列出它们,请使用:

for dirname in sorted(dirs, key=int):

若要对字母数字字符串排序,请使用 很自然

os.walk()在每个步骤中产生它在接下来的步骤中将要做什么。您可以在每个步骤中按照您希望的方式对列表进行排序,从而影响后续步骤的顺序。引用 2.7版手册:

当 topdown 为 True 时,调用者可以就地修改目录列表(可能使用 del 或片分配) ,walk ()只会递归到目录中保留名称的子目录中; 这可以用来删除搜索,强制执行特定的访问顺序

因此,对 dirNames进行排序将影响它们被访问的顺序:

for rootName, dirNames, fileNames in os.walk(path):
dirNames.sort()  # you may want to use the args cmp, key and reverse here

在此之后,就地排序 dirNames,并相应地排序下一个取得的 walk值。

当然,您也可以对 fileNames的列表进行排序,但这不会影响任何进一步的步骤(因为文件没有后代 walk将访问)。

当然,您可以根据 unutbu 的回答建议迭代这些列表的排序版本,但这不会影响 walk本身的进一步发展。

值的未修改顺序未被 os.walk定义,这意味着它将是“任意”顺序。你不应该依赖于你今天的经历。但实际上,它可能是底层文件系统返回的内容。在某些文件系统中,这将按字母顺序排列。

最简单的方法是对 os.walk()的返回值进行排序,例如:

for rootName, dirNames, fileNames in sorted(os.walk(path)):
#root, dirs and files are iterated in order...