Ответ 1
Я думаю, что порядок имеет отношение к тому, как файлы индексируются в вашей файловой системе. Если вы действительно хотите, чтобы он придерживался определенного порядка, вы всегда можете отсортировать список после получения файлов.
Я часто использую python для обработки каталогов данных. Недавно я заметил, что порядок списков по умолчанию изменился на нечто почти бессмысленное. Например, если я в текущем каталоге, содержащем следующие подкаталоги: run01, run02,... run19, run20, а затем создаю список из следующей команды:
dir = os.listdir(os.getcwd())
то я обычно получаю список в следующем порядке:
dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]
и так далее. Порядок был буквенно-цифровым. Но этот новый порядок остался со мной на некоторое время.
Что определяет (отображается) порядок этих списков?
Я думаю, что порядок имеет отношение к тому, как файлы индексируются в вашей файловой системе. Если вы действительно хотите, чтобы он придерживался определенного порядка, вы всегда можете отсортировать список после получения файлов.
Вы можете использовать встроенную функцию sorted
для сортировки строк, как вы хотите. Основываясь на том, что вы описываете,
sorted(os.listdir(whatever_directory))
В качестве альтернативы вы можете использовать метод .sort
списка:
lst = os.listdir(whatever_directory)
lst.sort()
Я думаю, должен сделать трюк.
Обратите внимание, что порядок, в котором os.listdir
получает имена файлов, вероятно, полностью зависит от вашей файловой системы.
В документации :
os.listdir(путь)
Возврат списка содержащие имена записей в каталог, заданный путем. Список находится в произвольном порядке. Это не включают специальные записи '.' а также "..", даже если они присутствуют в каталог.
На заказ нельзя полагаться и является артефактом файловой системы.
Чтобы отсортировать результат, используйте sorted(os.listdir(path))
.
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(...))
Вероятно, это просто порядок, возвращаемый 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, и они оба дали мне отсортированный результат, поэтому я не могу воспроизвести то, что вы видите.
Я обнаружил, что "сортировка" не всегда делает то, что я ожидал. например, у меня есть каталог, как показано ниже, и "сортировка" дает мне очень странный результат:
>>> 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']
Кажется, он сначала сравнивает первый символ, если он самый большой, он будет последним.
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.
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]))
Предлагаемая комбинация команд os.listdir и отсортированных генерирует тот же результат, что и команда ls -l под Linux. Следующий пример проверяет это предположение:
[email protected]:/tmp/test$ touch 3a 4a 5a b c d1 d2 d3 k l p0 p1 p3 q 410a 409a 408a 407a
[email protected]:/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
[email protected]:/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()
[email protected]:/tmp/test$
Итак, для тех, кто хочет воспроизвести результат известной команды ls -l в своем коде на Python, sorted (os.listdir(DIR)) работает очень хорошо.
Ответ Эллиота прекрасно ее решает, но поскольку это комментарий, он остается незамеченным, поэтому, чтобы помочь кому-то, я повторяю его как решение.
Использовать библиотеку natsort:
Установите библиотеку со следующей командой для Ubuntu и других версий Debian
Python 2
sudo pip install natsort
Python 3
sudo pip3 install natsort
Подробная информация о том, как использовать эту библиотеку, находится здесь
Я думаю, что по умолчанию порядок определяется значением ASCII. Решение этой проблемы заключается в следующем
dir = sorted(os.listdir(os.getcwd()), key=len)