我担心os.walk()
给出的文件和目录的顺序。如果我有这些目录,1
,10
,11
,12
,2
,20
,21
,{{ 1}},22
,3
,30
,31
,输出列表的顺序是什么?
是按数值排序吗?
32
或按ASCII值排序,例如1 2 3 10 20 30 11 21 31 12 22 32
给出的内容?
ls
此外,我如何获得特定的排序?
答案 0 :(得分:77)
os.walk
使用os.listdir
。以下是os.listdir
的文档字符串:
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)
(注意dirnames是字符串而不是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):
要对字母数字字符串进行排序,请使用natural sort。
答案 1 :(得分:34)
os.walk()
在每个步骤中产生将在接下来的步骤中执行的操作。您可以在每个步骤中通过按照您希望的方式对列表进行排序来影响后续步骤的顺序。引用the 2.7 manual:
当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
未定义值的未修改顺序,这意味着它将是“任意”顺序。你不应该依赖你今天的经历。但实际上它可能是底层文件系统返回的内容。在某些文件系统中,这将按字母顺序排列。
答案 2 :(得分:24)
最简单的方法是对os.walk()
的返回值进行排序,例如使用:
for rootName, dirNames, fileNames in sorted(os.walk(path)):
#root, dirs and files are iterated in order...