Como é pedido o Pythons glob.glob?

199

Eu escrevi o seguinte código 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

Agora eu entendi:

/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 que maneira é pedido?

Pode ajudá-lo a obter minha saída 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

Não está ordenado por nome de arquivo ou tamanho.

Outros links: glob,ls

Martin Thoma
fonte
2
A resposta final parece ser que o lspróprio comando classifica os arquivos por nome. 'ls -U' fornece uma lista não ordenada de arquivos em "ordem de diretório".
9788 Brian Peterson #
2
No Windows, ele foi classificado, então eu assumi que é sempre assim. Agora, no Ubuntu, isso me custa depurar. Nota para ler automaticamente a API! : 0)
Yuri Feldman
O comportamento é o mesmo com os.listdir: * O nix OS retorna arquivos em uma ordem não alfabética e (vergonha de me surpreender!) Isso está explícito na documentação : "A lista está em ordem arbitrária".
Joël

Respostas:

112

Provavelmente não está classificado e usa a ordem em que as entradas aparecem no sistema de arquivos, ou seja, a que você obtém ao usar ls -U. (Pelo menos na minha máquina, isso produz a mesma ordem que as globcorrespondências da lista ).

Xion
fonte
1
Sim, a menos que faça um esforço especial, ele simplesmente mostrará as entradas conforme o sistema operacional fornecer. O mesmo que o comando "find" no Unix, apenas despeja as entradas na ordem em que elas vêm da estrutura de dados usada pelo sistema de arquivos subjacente. Você não deve fazer nenhuma suposição sobre sua ordem, mesmo que você veja que os arquivos parecem aparecer na ordem de criação.
Raúl Salinas-Monteagudo
421

A ordem é arbitrária, mas você mesmo pode classificá-las

Se você deseja classificar por nome:

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

classificados por tempo de modificação:

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

ordenado por tamanho:

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

etc.

John La Rooy
fonte
1
Tenho arquivos, onde os nomes são apenas números inteiros, sem extensão, então eu uso: files = glob.glob('teksty/*'). A ordem pelo nome será concedida?
andilabs
3
@ mgalgs Não, essa não era a pergunta que eu realmente queria fazer. O que eu queria saber foi respondido por Xion.
Martin Thoma
E quanto a classificá-lo por data de criação, mas de acordo com a hora da criação. Porque está me listando primeiro os arquivos mais recentes. Como posso obter uma lista dos arquivos antigos para os mais recentes? Obrigado!
21818 joaquindev
1
Note-se que getmtime e getSize são relativamente caros - fazendo isso há um monte de arquivos pode demorar um pouco ..
drevicko
53

Ao verificar o código-fonte, glob.globvocê vê que ele chama internamente os.listdir, descrito aqui:

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

Sentença chave: os.listdir (caminho) Retorna uma lista contendo os nomes das entradas no diretório fornecido por caminho. A lista está em ordem arbitrária. Não inclui as entradas especiais '.' e '..' mesmo se eles estiverem presentes no diretório

Ordem arbitrária . :)

Ray Toal
fonte
14

glob.glob () é um invólucro em torno do os.listdir (), portanto o SO subjacente é responsável pela entrega dos dados. Em geral: você não pode fazer uma suposição sobre a encomenda aqui. A suposição básica é: sem pedidos. Se você precisar de uma classificação: classifique no nível do aplicativo.

Andreas Jung
fonte
13

A ordem é arbitrária, mas existem várias maneiras de classificá-las. Um deles é o seguinte:

#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
fonte
O que sua resposta contribui em comparação com as respostas existentes?
Martin Thoma
2
@ MartinThoma Eu tenho um problema com a classificação de não classificar os nomes de arquivos se os números inteiros presentes nos arquivos não forem preenchidos com zero. A classificação começa em 1000, sobe para o número inteiro mais alto e depois recomeça a partir do número inteiro menor. Se eu zerar os números, apenas a chamada ordenada nos arquivos os classifica perfeitamente. Então, acho que essa solução resolve o problema quando classificada sozinha não funciona.
precisa saber é o seguinte
1
@ Will.Evo Tente usar natsort: from natsort import natsorted; files = natsorted(files).
Martin Thoma
Sua resposta ajudou!
Vineet 19/01
12

Eu tive um problema semelhante, globestava retornando uma lista de nomes de arquivos em uma ordem arbitrária, mas queria percorrê-los em ordem numérica, conforme indicado pelo nome do arquivo. Foi assim que consegui:

Meus arquivos foram retornados 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"]

Classifiquei a lista no lugar, para isso, criei uma função:

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

Essa função retorna a parte numérica do nome do arquivo e é convertida em um número inteiro. Em seguida, chamei o método de classificação na lista como tal:

myList.sort(key=sortKeyFunc)

Isso retornou uma 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
fonte
Eu acho que é mais elegante usar em os.path.splitext(os.path.basename(s))[0]vez de os.path.basename(s)[:-4], então a definição da função será. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit
1

Se você está se perguntando o que o glob.glob fez no seu sistema no passado e não pode adicionar uma sortedchamada, a ordem será consistente nos sistemas de arquivos Mac HFS + e a ordem transversal em outros sistemas Unix. Portanto, provavelmente será determinístico, a menos que o sistema de arquivos subjacente tenha sido reorganizado, o que pode acontecer se os arquivos forem adicionados, removidos, renomeados, excluídos, movidos, etc.

crizCraig
fonte
E o APFS no macOS?
Boris
0

Na solução de @Johan La Rooy, classificar as imagens usando sorted(glob.glob('*.png'))não funciona para mim, a lista de saída ainda não está ordenada por seus nomes.

No entanto, isso sorted(glob.glob('*.png'), key=os.path.getmtime)funciona perfeitamente.

Estou um pouco confuso, como a classificação por seus nomes não funciona aqui.

Obrigado a @Martin Thoma por postar esta ótima pergunta e a @Johan La Rooy pelas soluções úteis.

Haoyu Wang
fonte
-1

Por favor, tente este código:

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

Foi assim que fiz meu caso particular. Espero que seja útil.

Elizabeth
fonte
1
Você deve alterar sua resposta para se adequar à pergunta.
usar o seguinte
1
A questão não é sobre classificação. Eu sei (e sabia naquela época) como classificar. A pergunta é sobre o pedido padrão.
Martin Thoma
1
Obrigado por este trecho de código, que pode fornecer ajuda imediata. Uma explicação adequada melhoraria bastante seu valor educacional, mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com perguntas semelhantes, mas não idênticas. Por favor edite sua resposta para adicionar explicação, e dar uma indicação do que limitações e premissas se aplicam.
precisa