¿Cómo se ordena Pythons glob.glob?

199

He escrito el siguiente código de 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

Ahora entiendo esto:

/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

¿De qué manera se ordena?

Podría ayudarlo a obtener mi salida 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

No está ordenado por nombre de archivo o tamaño.

Otros enlaces: glob,ls

Martin Thoma
fuente
2
La respuesta final parece ser que el lscomando en sí clasifica los archivos por nombre. 'ls -U' proporciona una lista desordenada de archivos en "orden de directorio".
Brian Peterson el
2
En Windows se ordenó, así que supuse que siempre era así ... ahora en Ubuntu me costó depurar. Nota para auto - leer la API! : 0)
Yuri Feldman
El comportamiento es el mismo con os.listdir: * nix OS devuelve los archivos en un orden bastante no alfabético, y (¡qué pena que me sorprendan!) Esto está explícito en la documentación : "La lista está en orden arbitrario".
Joël

Respuestas:

112

Probablemente no esté ordenado en absoluto y utiliza el orden en que aparecen las entradas en el sistema de archivos, es decir, el que se obtiene al usar ls -U. (Al menos en mi máquina, esto produce el mismo orden que enumerar globcoincidencias).

Xion
fuente
1
Sí, a menos que haga un esfuerzo especial, simplemente mostrará las entradas tal como las proporciona el sistema operativo. Al igual que el comando "buscar" en Unix, simplemente voltea las entradas en el orden en que provienen de la estructura de datos utilizada por el sistema de archivos subyacente. No debe hacer suposiciones sobre su ordenación, incluso si ve que los archivos parecen aparecer en el orden de creación.
Raúl Salinas-Monteagudo
421

El orden es arbitrario, pero puede ordenarlos usted mismo

Si quieres ordenar por nombre:

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

ordenado por hora de modificación:

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

ordenado por tamaño:

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

etc.

John La Rooy
fuente
1
Tengo archivos, donde los nombres son sólo números enteros, sin extensión, por lo que utilizo: files = glob.glob('teksty/*'). ¿Se otorgará el pedido por nam?
andilabs
3
@mgalgs No, esa no era la pregunta que realmente quería hacer. Lo que quería saber fue respondido por Xion.
Martin Thoma
¿Y qué hay de ordenarlo por fecha de creación pero de acuerdo con el tiempo de creación? Porque me está enumerando primero los archivos más recientes. ¿Cómo puedo obtener una lista de archivos antiguos a nuevos? ¡Gracias!
joaquindev
1
Tenga en cuenta que getmtime y getSize son relativamente caros - haciendo esto por una gran cantidad de archivos puede tomar un tiempo ..
drevicko
53

Al verificar el código fuente glob.glob, verá que llama internamente os.listdir, como se describe aquí:

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

Oración clave: os.listdir (ruta) Devuelve una lista que contiene los nombres de las entradas en el directorio dado por ruta. La lista está en orden arbitrario. No incluye las entradas especiales '.' y '...' incluso si están presentes en el directorio.

Orden arbitrario . :)

Ray Toal
fuente
14

glob.glob () es un contenedor alrededor de os.listdir (), por lo que el sistema operativo subyacente se encarga de entregar los datos. En general: no puede hacer una suposición sobre el pedido aquí. La suposición básica es: sin ordenar. Si necesita algún tipo de clasificación: ordene en el nivel de la aplicación.

Andreas Jung
fuente
13

El orden es arbitrario, pero hay varias formas de ordenarlos. Uno de ellos es el siguiente:

#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]))
abril
fuente
¿Qué aporta su respuesta en comparación con las respuestas existentes?
Martin Thoma
2
@ MartinThoma Tengo un problema con la ordenación, no la ordenación de los nombres de archivo si los enteros presentes en los archivos no están rellenados con ceros. La clasificación comienza en 1000, sube a lo que sea el número entero más alto y luego comienza de nuevo desde el número entero más pequeño. Si pongo a cero los números, solo llamar ordenado en los archivos los ordena perfectamente. Por lo tanto, creo que esta solución resuelve el problema cuando ordenada sola no funciona.
Will.Evo
1
@ Will.Evo Intente utilizar natsort: from natsort import natsorted; files = natsorted(files).
Martin Thoma
Tu respuesta ayudó!
Vineet
12

Tuve un problema similar, globestaba devolviendo una lista de nombres de archivo en un orden arbitrario, pero quería revisarlos en orden numérico como lo indica el nombre del archivo. Así es como lo logré:

Mis archivos fueron devueltos por globalgo como:

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

Ordene la lista en su lugar, para hacer esto creé una función:

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

Esta función devuelve la parte numérica del nombre del archivo y la convierte en un entero. Luego llamé al método de clasificación en la lista como tal:

myList.sort(key=sortKeyFunc)

Esto devolvió una lista como tal:

["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
fuente
Creo que es más elegante de usar en os.path.splitext(os.path.basename(s))[0]lugar de os.path.basename(s)[:-4], por lo que la definición de la función será. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit
1

Si se pregunta qué ha hecho glob.glob en su sistema en el pasado y no puede agregar una sortedllamada, el orden será consistente en los sistemas de archivos Mac HFS + y será un orden transversal en otros sistemas Unix. Por lo tanto, es probable que haya sido determinista a menos que se haya reorganizado el sistema de archivos subyacente, lo que puede suceder si se agregan, eliminan, renombran, eliminan, mueven, etc.

crizCraig
fuente
¿Qué pasa con APFS en macOS?
Boris
0

De la solución de @Johan La Rooy, ordenar las imágenes usando sorted(glob.glob('*.png'))no funciona para mí, la lista de salida todavía no está ordenada por sus nombres.

Sin embargo, sorted(glob.glob('*.png'), key=os.path.getmtime)funciona perfectamente.

Estoy un poco confundido sobre cómo la clasificación por sus nombres no funciona aquí.

Agradezca a @ Martin Thoma por publicar esta gran pregunta y a @Johan La Rooy por las soluciones útiles.

Haoyu Wang
fuente
-1

Por favor intente este código:

sorted(glob.glob( os.path.join(path, '*.png') ),key=lambda x:float(re.findall("([0-9]+?)\.png",x)[0]))
faris
fuente
-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])

Así es como hice mi caso particular. Espero que sea útil.

Elizabeth
fuente
1
Debe cambiar su respuesta para que se ajuste a la pregunta.
CodenameLambda
1
La pregunta no es sobre la clasificación. Sé (y sabía entonces) cómo ordenar. La pregunta es sobre el orden predeterminado.
Martin Thoma
1
Gracias por este fragmento de código, que puede proporcionar ayuda inmediata. Una explicación adecuada mejoraría en gran medida su valor educativo al mostrar por qué esta es una buena solución al problema, y ​​la haría más útil para futuros lectores con preguntas similares, pero no idénticas. Por favor, editar su respuesta para agregar explicación y dar una indicación de lo que se aplican limitaciones y supuestos.
Toby Speight