os.walk Mac和Linux上的不同文件夹排序?

ghu*_*ill 0 python linux macos os.walk python-3.5

给定以下文件结构,

??? 0=ocfl_object_1.0
??? inventory.json
??? inventory.json.md5
??? v1
?   ??? content
?   ?   ??? foo.xml
?   ?   ??? level1
?   ?       ??? level2
?   ?           ??? bar.txt
?   ??? inventory.json
?   ??? inventory.json.md5
??? v2
    ??? content
    ?   ??? duck.txt
    ??? inventory.json
    ??? inventory.json.md5
Run Code Online (Sandbox Code Playgroud)

我想知道python的os.walk函数是否有可能在Mac和Linux上以不同的顺序返回文件夹?两者都使用python 3.5.

苹果电脑:

In [15]: for root,folders,files in os.walk('foo/bar'): 
    ...:     print(folders,files) 
    ...:                                                                                                                                                                                                                                                                                   
['v1', 'v2'] ['inventory.json', '0=ocfl_object_1.0', 'inventory.json.md5']
['content'] ['inventory.json', 'inventory.json.md5']
['level1'] ['foo.xml']
['level2'] []
[] ['bar.txt']
['content'] ['inventory.json', 'inventory.json.md5']
[] ['duck.txt']
Run Code Online (Sandbox Code Playgroud)

在Linux上:

In [54]: for root,folders,files in os.walk('foo/bar'): 
    ...:     print(folders,files) 
    ...:                                                                                                                                                                                                                                                                                   
['v2', 'v1'] ['inventory.json.md5', 'inventory.json', '0=ocfl_object_1.0']
['content'] ['inventory.json.md5', 'inventory.json']
[] ['duck.txt']
['content'] ['inventory.json.md5', 'inventory.json']
['level1'] ['foo.xml']
['level2'] []
[] ['bar.txt']
Run Code Online (Sandbox Code Playgroud)

在Mac的情况下,看起来好像v1首先遇到文件夹,而在Linux上它是v2.有关为什么会出现这种情况的任何见解?

r.o*_*ook 5

请参阅相关部分的文档os.walk:

版本3.5中已更改:此函数现在调用os.scandir()而不是os.listdir()通过减少调用次数来加快速度 os.stat().

然后在os.scandir():

返回os.DirEntry与path给出的目录中的条目对应的对象的迭代器.这些条目产生以任意顺序,特殊项目'.''..'不包括在内.

不管listdir()或者scandir(),二者都以任意顺序无论如何返回.

简而言之是不可预期的.


话虽如此,你应该能够dirnames基于这个部分操纵循环:

自上而下的True,来电者可以修改dirnames中列表就地 (可能使用delslice转让),并且walk()只会递归到他们的名字留在子目录dirnames中 ; 这可用于修剪搜索,强制执行特定的访问顺序,甚至可以walk()walk()再次恢复之前通知调用者创建或重命名的目录.修改dirnames中,当自上而下的就是 False对行走的行为没有影响,因为在自下而上的模式在目录dirnames中被之前生成dirpath生成本身.

所以,如果你folders.sort()应该根据你的sorted订单工作.我只是尝试过它,它的工作原理.我还将关键部分加粗到位 - folders必须按顺序排序os.walk()以便接受订单:

for root,folders,files in os.walk('foo/bar'): 
    folders.sort()   # <--- sort your folders to impose the order. 
    print(folders,files) 
Run Code Online (Sandbox Code Playgroud)