来自os.listdir()的非字母数字列表顺序

时间:2011-01-27 05:30:30

标签: python list directory-listing listdir

我经常使用python来处理数据目录。最近,我注意到列表的默认顺序已经变为几乎荒谬的东西。例如,如果我在包含以下子目录的当前目录中:run01,run02,... run19,run20,然后我从以下命令生成一个列表:

dir = os.listdir(os.getcwd())

然后我通常会按此顺序获得一个列表:

dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]

等等。订单曾经是字母数字。但是这个新订单现在已经存在了我一段时间。

什么是确定这些列表的(显示)顺序?

13 个答案:

答案 0 :(得分:94)

您可以使用内置sorted函数对字符串进行排序。根据您的描述,

sorted(os.listdir(whatever_directory))

或者,您可以使用列表的.sort方法:

lst = os.listdir(whatever_directory)
lst.sort()

我认为应该这样做。

请注意os.listdir获取文件名的顺序可能完全取决于您的文件系统。

答案 1 :(得分:48)

我认为订单与FileSystem上文件索引的方式有关。 如果你真的想让它遵守某些订单,你可以在获取文件后对列表进行排序。

答案 2 :(得分:38)

根据documentation

  

os.listdir(路径)

     
    

返回一个清单     包含条目的名称     path给出的目录。 列表     按任意顺序。它不是     包括特殊条目'。'和     '..'即使他们出现在     。目录

  

不能依赖订单,它是文件系统的工件。

要对结果进行排序,请使用sorted(os.listdir(path))

答案 3 :(得分:12)

Python无论出于何种原因都没有内置的方法来进行自然排序(意思是1,2,10而不是1,10,2),所以你必须自己编写:

import re
def sorted_aphanumeric(data):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(data, key=alphanum_key)

您现在可以使用此功能对列表进行排序:

dirlist = sorted_aphanumeric(os.listdir(...))

答案 4 :(得分:5)

这可能就是C readdir()返回的顺序。尝试运行这个C程序:

#include <dirent.h>
#include <stdio.h>
int main(void)
{   DIR *dirp;
    struct dirent* de;
    dirp = opendir(".");
    while(de = readdir(dirp)) // Yes, one '='.
        printf("%s\n", de->d_name);
    closedir(dirp);
    return 0;
}

构建行应该类似于gcc -o foo foo.c

P.S。刚刚运行了这个和你的Python代码,他们都给了我排序的输出,所以我无法重现你所看到的。

答案 5 :(得分:2)

我发现“排序”并不总能达到我的预期。例如,我有一个如下目录,“排序”给我一个非常奇怪的结果:

>>> os.listdir(pathon)
['2', '3', '4', '5', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472']
>>> sorted([ f for f in os.listdir(pathon)])
['2', '3', '4', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472', '5']

似乎首先将第一个角色进行比较,如果是最大的那个,那将是最后一个角色。

答案 6 :(得分:2)

我认为默认情况下顺序由ASCII值确定。这个问题的解决方案是

dir = sorted(os.listdir(os.getcwd()), key=len)

答案 7 :(得分:1)

In [6]: os.listdir?

Type:       builtin_function_or_method
String Form:<built-in function listdir>
Docstring:
listdir(path) -> list_of_strings
Return a list containing the names of the entries in the directory.
path: path of directory to list
The list is in **arbitrary order**.  It does not include the special
entries '.' and '..' even if they are present in the directory.

答案 8 :(得分:1)

aaa = ['row_163.pkl', 'row_394.pkl', 'row_679.pkl', 'row_202.pkl', 'row_1449.pkl', 'row_247.pkl', 'row_1353.pkl', 'row_749.pkl', 'row_1293.pkl', 'row_1304.pkl', 'row_78.pkl', 'row_532.pkl', 'row_9.pkl', 'row_1435.pkl']                                                                                                                                                                                                                                                                                                 
sorted(aaa, key=lambda x: int(os.path.splitext(x.split('_')[1])[0]))

如果遇到我的要求,我的情况如row_163.pkl此处os.path.splitext('row_163.pkl')会将其分解为('row_163', '.pkl'),因此需要根据“_”进行拆分。

但如果您有要求,可以执行类似

的操作
sorted(aa, key = lambda x: (int(re.sub('\D','',x)),x))

其中

aa = ['run01', 'run08', 'run11', 'run12', 'run13', 'run14', 'run18']

并且对于目录检索,您可以执行sorted(os.listdir(path))

对于类似'run01.txt''run01.csv'的情况,您可以这样做

sorted(files, key=lambda x : int(os.path.splitext(x)[0]))

答案 9 :(得分:1)

来自documentation

  

列表以任意顺序,并且不包括特殊条目“。”。和“ ..”,即使它们存在于目录中。

这意味着顺序可能取决于OS /文件系统,没有特别有意义的顺序,因此不能保证特定顺序。提到了很多答案:如果需要,可以对检索到的列表进行排序。

干杯:)

答案 10 :(得分:0)

os.listdir 排序命令的建议组合在Linux下生成与 ls -l <​​/ strong>命令相同的结果。以下示例验证了此假设:

user@user-PC:/tmp/test$ touch 3a 4a 5a b c d1 d2 d3 k l p0 p1 p3 q 410a 409a 408a 407a
user@user-PC:/tmp/test$ ls -l
total 0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 3a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 407a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 408a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 409a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 410a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 4a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 5a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 b
-rw-rw-r-- 1 user user 0 Feb  15 10:31 c
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d2
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 k
-rw-rw-r-- 1 user user 0 Feb  15 10:31 l
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 q

user@user-PC:/tmp/test$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.listdir( './' )
['d3', 'k', 'p1', 'b', '410a', '5a', 'l', 'p0', '407a', '409a', '408a', 'd2', '4a', 'p3', '3a', 'q', 'c', 'd1']
>>> sorted( os.listdir( './' ) )
['3a', '407a', '408a', '409a', '410a', '4a', '5a', 'b', 'c', 'd1', 'd2', 'd3', 'k', 'l', 'p0', 'p1', 'p3', 'q']
>>> exit()
user@user-PC:/tmp/test$ 

因此,对于想要在其Python代码中重现众所周知的 ls -l <​​/ strong>命令的结果的人,已排序(os.listdir(DIR))效果很好。

答案 11 :(得分:0)

Elliot's答案可以完美解决,但由于它是评论,因此并未引起人们的注意,因此为了帮助他人,我重申此为解决方案。

使用natsort库:

使用以下命令为Ubuntu和其他Debian版本安装库

Python 2

sudo pip install natsort

Python 3

sudo pip3 install natsort

有关如何使用此库的详细信息,请参见here

答案 12 :(得分:0)

ls 默认预览按名称排序的文件。 (ls 选项可用于按日期、大小等排序)

files = list(os.popen("ls"))
files = [file.strip("\n") for file in files]

当目录包含这么多文件时,使用 ls 会获得更好的性能。