Як замовляється Pythons 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 повертає файли у зовсім не алфавітному порядку, і (соромно, щоб мене здивували!) Це прямо в документації : "Список у довільному порядку".
Joël

Відповіді:


112

Він, ймовірно, не сортується зовсім і використовує порядок, коли записи з'являються у файловій системі, тобто той, який ви отримуєте при використанні ls -U. (Принаймні, на моїй машині це створює той самий порядок, що і перелік globвідповідностей).


1
Так, якщо ви не докладете особливих зусиль, він просто покаже записи, як це забезпечує операційна система. Так само, як команда "знайти" в Unix, вона просто скидає записи в тому порядку, в якому вони надходять із структури даних, використовуваної базовою файловою системою. Ви не повинні робити жодних припущень щодо його впорядкування, навіть якщо ви бачите, що файли здаються в порядку створення.
Рауль Салінас-Монтеагудо

421

Замовлення довільне, але ви можете їх сортувати самостійно

Якщо ви хочете відсортувати за назвою:

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 Ні, це не те питання, яке я насправді хотів задати. Що я хотів знати, відповів Сіон.
Мартін Тома

А що з сортуванням за датою створення, але відповідно до часу створення. Тому що він перераховує мені першими найсвіжіші файли Як я можу отримати список від старих до файлів, які не розміщуються? Дякую!
joaquindev

1
Зауважте, що getmtime та getize є відносно дорогими - це може зайняти багато файлів.
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

@ 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"]

Я думаю, що це більш елегантно використовувати 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. Таким чином, це, ймовірно, буде детермінованим, якщо не буде реорганізована базова файлова система, що може статися, якщо файли будуть додані, видалені, перейменовані, видалені, переміщені тощо ...


А як щодо 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]))

-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
Дякуємо за цей фрагмент коду, який може надати негайну допомогу. Правильне пояснення значно покращило б його навчальну цінність, показавши чому це хороше рішення проблеми, та зробило б її кориснішою для майбутніх читачів із подібними, але не однаковими питаннями. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Toby Speight
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.