Come viene ordinato Pythons glob.glob?


199

Ho scritto il seguente codice 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

Ora capisco questo:

/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

In che modo viene ordinato?

Potrebbe aiutarti ad ottenere il mio output 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

Non è ordinato per nome file o dimensione.

Altri link: glob,ls


2
La risposta finale sembra essere che il lscomando stesso ordina i file per nome. 'ls -U' fornisce un elenco non ordinato di file in "ordine di directory".
Brian Peterson,

2
Su Windows è stato ordinato, quindi ho pensato che fosse sempre così ... ora su Ubuntu mi è costato il debug. Nota per auto - leggere l'api! : 0)
Yuri Feldman,

Il comportamento è lo stesso con os.listdir: * nix OS restituisce i file in un ordine quasi non alfabetico e (peccato per me essere sorpreso!) Questo è esplicito nella documentazione : "L'elenco è in ordine arbitrario".
Joël,

Risposte:


112

Probabilmente non è affatto ordinato e usa l'ordine in cui le voci appaiono nel filesystem, cioè quello che ottieni quando lo usi ls -U. (Almeno sulla mia macchina questo produce lo stesso ordine delle globcorrispondenze di elenco ).


1
Sì, a meno che non compia uno sforzo particolare, mostrerà semplicemente le voci fornite dal sistema operativo. Come il comando "trova" in Unix, scarica le voci nell'ordine in cui provengono dalla struttura di dati utilizzata dal file system sottostante. Non dovresti fare ipotesi sul suo ordinamento, anche se vedresti che i file sembrano apparire nell'ordine di creazione.
Raúl Salinas-Monteagudo,

421

L'ordine è arbitrario, ma puoi ordinarli tu stesso

Se vuoi ordinato per nome:

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

ordinati per tempo di modifica:

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

ordinati per dimensione:

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

eccetera.


1
Ho i file, dove i nomi sono solo numeri interi, senza estensione, per cui uso: files = glob.glob('teksty/*'). L'ordine per nome sarà concesso?
Andilab

3
@mgalgs No, non era questa la domanda che volevo davvero porre. Quello che volevo sapere è stato risposto da Xion.
Martin Thoma,

E per quanto riguarda l'ordinamento per data di creazione ma in base al momento della creazione. Perché mi elenca prima i file più recenti. Come posso ottenere un elenco dai file più vecchi a quelli più recenti? Grazie!
joaquindev,

1
Nota che getmtime e getsize sono relativamente costosi - farlo per molti file potrebbe richiedere del tempo ..
drevicko,

53

Controllando il codice sorgente di glob.globte vedi che chiama internamente os.listdir, descritto qui:

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

Frase chiave: os.listdir (percorso) Restituisce un elenco contenente i nomi delle voci nella directory fornite dal percorso. L'elenco è in ordine arbitrario. Non include le voci speciali "." e '..' anche se sono presenti nella directory.

Ordine arbitrario . :)


14

glob.glob () è un wrapper attorno a os.listdir (), quindi il sistema operativo sottostante è responsabile della consegna dei dati. In generale: qui non è possibile ipotizzare l'ordine. Il presupposto di base è: nessun ordine. Se hai bisogno di un ordinamento: ordina a livello di applicazione.


13

L'ordine è arbitrario, ma ci sono diversi modi per ordinarli. Uno di questi è il seguente:

#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]))

In che cosa contribuisce la tua risposta rispetto alle risposte esistenti?
Martin Thoma,

2
@MartinThoma Ho un problema con l'ordinamento non ordinare i nomi dei file se gli interi presenti nei file non sono a zero. L'ordinamento inizia da 1000, sale a qualunque sia il numero intero più alto e quindi ricomincia dal numero intero più piccolo. Se azzerare i numeri, basta chiamare ordinati sui file per ordinarli perfettamente. Quindi penso che questa soluzione risolva il problema quando ordinata da sola non funziona.
Will.Evo,

1
@ Will.Evo Provare a utilizzare natsort: from natsort import natsorted; files = natsorted(files).
Martin Thoma,

La tua risposta ha aiutato!
Vineet

12

Avevo un problema simile, globrestituivo un elenco di nomi di file in un ordine arbitrario ma volevo esaminarli in ordine numerico come indicato dal nome del file. Ecco come l'ho raggiunto:

I miei file sono stati restituiti da globqualcosa del tipo:

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

Ho ordinato l'elenco in posizione, per fare ciò ho creato una funzione:

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

Questa funzione restituisce la parte numerica del nome del file e la converte in un numero intero. Ho quindi chiamato il metodo di ordinamento nell'elenco come tale:

myList.sort(key=sortKeyFunc)

Ciò ha restituito un elenco come tale:

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

Penso che sia più elegante da usare os.path.splitext(os.path.basename(s))[0]anziché os.path.basename(s)[:-4], quindi sarà la definizione della funzione. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit

1

Se ti stai chiedendo cosa ha fatto glob.glob sul tuo sistema in passato e non puoi aggiungere una sortedchiamata, l'ordinamento sarà coerente sui filesystem Mac HFS + e sarà un ordine trasversale su altri sistemi Unix. Quindi sarà probabilmente deterministico a meno che il filesystem sottostante non sia stato riorganizzato, cosa che può accadere se i file fossero aggiunti, rimossi, rinominati, cancellati, spostati, ecc ...


Che dire di APFS su macOS?
Boris,

0

Dalla soluzione di @Johan La Rooy, l'ordinamento delle immagini utilizzando sorted(glob.glob('*.png'))non funziona per me, l'elenco di output non è ancora ordinato in base ai loro nomi.

comunque, il sorted(glob.glob('*.png'), key=os.path.getmtime) funziona perfettamente.

Sono un po 'confuso come può l'ordinamento in base ai loro nomi non funziona qui.

Grazie a @Martin Thoma per aver pubblicato questa fantastica domanda e @Johan La Rooy per le utili soluzioni.


-1

Per favore prova questo codice:

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])

È così che ho fatto il mio caso particolare. Spero sia utile.


1
È necessario modificare la risposta per adattarla alla domanda.
Nome in codice

1
La domanda non riguarda l'ordinamento. So (e sapevo allora) come ordinare. La domanda riguarda l'ordine predefinito.
Martin Thoma,

1
Grazie per questo frammento di codice, che può fornire un aiuto immediato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore educativo mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con domande simili, ma non identiche. Si prega di modificare la risposta di aggiungere una spiegazione, e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
Toby Speight,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.