Как питоны заказывают glob.glob?

199

Я написал следующий код Python:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, glob

path = '/home/my/path'
for infile in glob.glob( os.path.join(path, '*.png') ):
    print infile

Теперь я получаю это:

/home/my/path/output0352.png
/home/my/path/output0005.png
/home/my/path/output0137.png
/home/my/path/output0202.png
/home/my/path/output0023.png
/home/my/path/output0048.png
/home/my/path/output0069.png
/home/my/path/output0246.png
/home/my/path/output0071.png
/home/my/path/output0402.png
/home/my/path/output0230.png
/home/my/path/output0182.png
/home/my/path/output0121.png
/home/my/path/output0104.png
/home/my/path/output0219.png
/home/my/path/output0226.png
/home/my/path/output0215.png
/home/my/path/output0266.png
/home/my/path/output0347.png
/home/my/path/output0295.png
/home/my/path/output0131.png
/home/my/path/output0208.png
/home/my/path/output0194.png

Каким образом это заказано?

Это может помочь вам получить мой вывод ls -l:

-rw-r--r-- 1 moose moose 627669 2011-07-17 17:26 output0005.png
-rw-r--r-- 1 moose moose 596417 2011-07-17 17:26 output0023.png
-rw-r--r-- 1 moose moose 543639 2011-07-17 17:26 output0048.png
-rw-r--r-- 1 moose moose 535384 2011-07-17 17:27 output0069.png
-rw-r--r-- 1 moose moose 543216 2011-07-17 17:27 output0071.png
-rw-r--r-- 1 moose moose 561776 2011-07-17 17:27 output0104.png
-rw-r--r-- 1 moose moose 501865 2011-07-17 17:27 output0121.png
-rw-r--r-- 1 moose moose 547144 2011-07-17 17:27 output0131.png
-rw-r--r-- 1 moose moose 530596 2011-07-17 17:27 output0137.png
-rw-r--r-- 1 moose moose 532567 2011-07-17 17:27 output0182.png
-rw-r--r-- 1 moose moose 553562 2011-07-17 17:27 output0194.png
-rw-r--r-- 1 moose moose 574065 2011-07-17 17:27 output0202.png
-rw-r--r-- 1 moose moose 552197 2011-07-17 17:27 output0208.png
-rw-r--r-- 1 moose moose 559809 2011-07-17 17:27 output0215.png
-rw-r--r-- 1 moose moose 549046 2011-07-17 17:27 output0219.png
-rw-r--r-- 1 moose moose 566661 2011-07-17 17:27 output0226.png
-rw-r--r-- 1 moose moose 561678 2011-07-17 17:27 output0246.png
-rw-r--r-- 1 moose moose 525550 2011-07-17 17:27 output0266.png
-rw-r--r-- 1 moose moose 565715 2011-07-17 17:27 output0295.png
-rw-r--r-- 1 moose moose 568381 2011-07-17 17:28 output0347.png
-rw-r--r-- 1 moose moose 532768 2011-07-17 17:28 output0352.png
-rw-r--r-- 1 moose moose 535818 2011-07-17 17:28 output0402.png

Это не упорядочено по имени файла или размеру.

Другие ссылки: glob,ls

Мартин Тома
источник
2
Окончательный ответ, похоже, заключается в том, что lsсама команда сортирует файлы по имени. 'ls -U' дает неупорядоченный список файлов в "порядке каталогов".
Брайан Петерсон
2
На Windows это было отсортировано, поэтому я просто предположил, что это всегда так ... теперь на Ubuntu это стоило мне отладки. Обратите внимание на себя - читайте API! : 0)
Юрий Фельдман
Поведение то же самое с os.listdir: * nix OS возвращает файлы в не алфавитном порядке, и (позор, что я удивлен!), Это явно указано в документации : «Список в произвольном порядке».
Жоэль

Ответы:

112

Вероятно, он вообще не сортируется и использует порядок, в котором записи появляются в файловой системе, то есть тот, который вы получаете при использовании ls -U. (По крайней мере, на моей машине это производит тот же порядок, что и список globсовпадений)

Xion
источник
1
Да, если только он не приложит особых усилий, он просто покажет записи в том виде, в котором их предоставляет операционная система. Так же, как команда «найти» в Unix, она просто выводит записи в порядке их поступления из структуры данных, используемой базовой файловой системой. Вы не должны делать никаких предположений относительно его порядка, даже если вы видите, что файлы, кажется, появляются в порядке создания.
Рауль Салинас-Монтеагудо
422

Заказ произвольный, но вы можете отсортировать их самостоятельно

Если вы хотите отсортировать по имени:

sorted(glob.glob('*.png'))

отсортировано по времени модификации:

import os
sorted(glob.glob('*.png'), key=os.path.getmtime)

отсортировано по размеру:

import os
sorted(glob.glob('*.png'), key=os.path.getsize)

и т.п.

Джон Ла Рой
источник
1
У меня есть файлы, где имена являются только целыми числами, без расширения, поэтому я использую: files = glob.glob('teksty/*'). Будет ли заказ предоставлен нам?
andilabs
3
@mgalgs Нет, это был не тот вопрос, который я действительно хотел задать. На то, что я хотел знать, ответил Сион.
Мартин Тома
А как насчет сортировки по дате создания, но по времени создания. Потому что он перечисляет мне в первую очередь новые файлы. Как я могу получить список старых и новых файлов? Спасибо!
Хоакиндев
1
Обратите внимание, что getmtime и getsize относительно дороги - выполнение этого для большого количества файлов может занять некоторое время ..
drevicko
53

Проверив исходный код, glob.globвы увидите, что он внутренне вызывает os.listdir, как описано здесь:

http://docs.python.org/library/os.html?highlight=os.listdir#os.listdir

Ключевое предложение: os.listdir (путь) Возвращает список, содержащий имена записей в каталоге, заданных путем. Список в произвольном порядке. Он не включает специальные записи "." и «..», даже если они присутствуют в каталоге.

Произвольный порядок . :)

Рэй Тоал
источник
14

glob.glob () - это оболочка для os.listdir (), так что лежащая в основе ОС отвечает за доставку данных. В общем: вы не можете сделать предположение о заказе здесь. Основное предположение: нет порядка. Если вам нужна сортировка: сортируйте на уровне приложения.

Андреас Юнг
источник
13

Порядок произвольный, но есть несколько способов их отсортировать. Один из них выглядит следующим образом:

#First, get the files:
import glob
import re
files =glob.glob1(img_folder,'*'+output_image_format)
# if you want sort files according to the digits included in the filename, you can do as following:
files = sorted(files, key=lambda x:float(re.findall("(\d+)",x)[0]))
апрель
источник
Что ваш ответ способствует по сравнению с существующими ответами?
Мартин Тома
2
@MartinThoma У меня проблема с сортировкой, не сортирующей имена файлов, если целые числа, присутствующие в файлах, не дополняются нулями. Сортировка начинается с 1000, возрастает до максимального целого числа, а затем начинается снова с наименьшего целого числа. Если я обнуляю числа, просто сортировка вызовов по файлам сортирует их идеально. Поэтому я думаю, что это решение решает проблему, когда сортировка не работает.
Will.Evo
1
@ Will.Evo Попробуйте использовать natsort: from natsort import natsorted; files = natsorted(files).
Мартин Тома
Ваш ответ помог!
Vineet
12

У меня была похожая проблема: globвозвращался список имен файлов в произвольном порядке, но я хотел просмотреть их в числовом порядке, как указано в имени файла. Вот как я этого добился:

Мои файлы были возвращены globчем-то вроде:

myList = ["c:\tmp\x\123.csv", "c:\tmp\x\44.csv", "c:\tmp\x\101.csv", "c:\tmp\x\102.csv", "c:\tmp\x\12.csv"]

Я отсортировал список на месте, для этого я создал функцию:

def sortKeyFunc(s):
    return int(os.path.basename(s)[:-4])

Эта функция возвращает числовую часть имени файла и преобразуется в целое число. Затем я вызвал метод сортировки в списке следующим образом:

myList.sort(key=sortKeyFunc)

Это вернул список как таковой:

["c:\tmp\x\12.csv", "c:\tmp\x\44.csv", "c:\tmp\x\101.csv", "c:\tmp\x\102.csv", "c:\tmp\x\123.csv"]
Hornbydd
источник
Я думаю, что это более элегантно использовать os.path.splitext(os.path.basename(s))[0]вместо os.path.basename(s)[:-4], так что определение функции будет. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit
1

Если вам интересно, что glob.glob делал в вашей системе в прошлом и не может добавить sortedвызов, порядок будет одинаковым для файловых систем Mac HFS + и будет обратным порядком в других системах Unix. Так что, скорее всего, он будет детерминированным, если базовая файловая система не будет реорганизована, что может произойти, если файлы были добавлены, удалены, переименованы, удалены, перемещены и т. Д.

crizCraig
источник
А как насчет APFS в macOS?
Борис
0

Из решения @Johan La Rooy, сортировка изображений, использующих sorted(glob.glob('*.png'))меня, не работает, список вывода по-прежнему не упорядочен по их именам.

Тем не менее, sorted(glob.glob('*.png'), key=os.path.getmtime)работает отлично.

Я немного запутался, как сортировка по их именам здесь не работает.

Спасибо @Martin Thoma за публикацию этого замечательного вопроса и @Johan La Rooy за полезные решения.

Хаою Ван
источник
-1

Пожалуйста, попробуйте этот код:

sorted(glob.glob( os.path.join(path, '*.png') ),key=lambda x:float(re.findall("([0-9]+?)\.png",x)[0]))
Faris
источник
-3
'''my file name is 
"0_male_0.wav", "0_male_2.wav"... "0_male_30.wav"... 
"1_male_0.wav", "1_male_2.wav"... "1_male_30.wav"... 
"8_male_0.wav", "8_male_2.wav"... "8_male_30.wav"

when I wav.read(files) I want to read them in a sorted torder, i.e., "0_male_0.wav"
"0_male_1.wav"
"0_male_2.wav" ...
"0_male_30.wav"
"1_male_0.wav"
"1_male_1.wav"
"1_male_2.wav" ...
"1_male_30.wav"
so this is how I did it.

Just take all files start with "0_*" as an example. Others you can just put it in a loop
'''

import scipy.io.wavfile as wav
import glob 
from os.path import isfile, join

#get all the file names in file_names. THe order is totally messed up
file_names = [f for f in listdir(audio_folder_dir) if isfile(join(audio_folder_dir, f)) and '.wav' in f] 
#find files that belongs to "0_*" group
filegroup0 = glob.glob(audio_folder_dir+'/0_*')
#now you get sorted files in group '0_*' by the last number in the filename
filegroup0 = sorted(filegroup0, key=getKey)

def getKey(filename):
    file_text_name = os.path.splitext(os.path.basename(filename))  #you get the file's text name without extension
    file_last_num = os.path.basename(file_text_name[0]).split('_')  #you get three elements, the last one is the number. You want to sort it by this number
    return int(file_last_num[2])

Вот как я сделал мой конкретный случай. Надеюсь, это полезно.

Элизабет
источник
1
Вы должны изменить свой ответ в соответствии с вопросом.
CodenameLambda
1
Вопрос не в сортировке. Я знаю (и тогда я знал), как сортировать. Вопрос о порядке по умолчанию.
Мартин Тома
1
Спасибо за этот фрагмент кода, который может оказать некоторую немедленную помощь. Правильное объяснение значительно повысило бы его образовательную ценность, показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с похожими, но не идентичными вопросами. Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение и указать, какие ограничения и предположения применяются.
Тоби Спейт