75

我担心 . 给出的文件和目录的顺序os.walk()。如果我有这些目录,1, 10, 11, 12, 2, 20, 21, 22, 3, 30, 31, 32, 输出列表的顺序是什么?

它是按数值排序的吗?

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

此外,我怎样才能获得特定的排序?

4

3 回答 3

114

os.walk使用os.listdir. 这是文档字符串os.listdir

列表目录(路径)-> list_of_strings

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

path: path of directory to list

该列表是任意顺序的。它不包括特殊条目“。” 和 '..' 即使它们存在于目录中。

(我的重点)。

但是,您可以使用它sort来确保您想要的顺序。

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

(请注意,目录名是字符串而不是整数,因此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):

要对字母数字字符串进行排序,请使用自然排序

于 2013-08-16T21:29:25.673 回答
46

os.walk()在每个步骤中产生它将在接下来的步骤中执行的操作。您可以在每个步骤中通过按照您想要的方式对列表进行排序来影响后续步骤的顺序。引用2.7 手册

当 topdown 为 True 时,调用者可以就地修改 dirnames 列表(可能使用 del 或 slice 赋值),并且 walk() 只会递归到名称保留在 dirnames 中的子目录;这可以用来修剪搜索,强加特定的访问顺序

所以排序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,这意味着它将是“任何”顺序。你不应该依赖你今天的经历。但实际上它可能是底层文件系统返回的内容。在某些文件系统中,这将按字母顺序排列。

于 2013-08-16T21:47:02.280 回答
44

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

for rootName, dirNames, fileNames in sorted(os.walk(path)):
    #root, dirs and files are iterated in order... 
于 2015-09-16T12:15:28.437 回答