Bagaimana cara Pythons glob.glob dipesan?

199

Saya telah menulis kode Python berikut:

#!/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

Sekarang saya mengerti:

/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

Di mana cara memesannya?

Mungkin membantu Anda untuk mendapatkan ls -l output saya:

-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

Ini tidak dipesan berdasarkan nama file atau ukuran.

Link lainnya: glob,ls

Martin Thoma
sumber
2
Jawaban terakhir tampaknya adalah bahwa lsperintah itu sendiri mengurutkan file dengan nama. 'ls -U' memberikan daftar file yang tidak terurut dalam "urutan direktori".
Brian Peterson
2
Di windows itu disortir jadi saya hanya berasumsi selalu begitu .. sekarang di Ubuntu biayanya debugging. Catatan untuk membaca sendiri api! : 0)
Yuri Feldman
Perilaku ini sama dengan os.listdir: * nix OS mengembalikan file dalam urutan yang tidak sesuai abjad, dan (memalukan saya untuk terkejut!) Ini secara eksplisit dalam dokumentasi : "Daftar ini dalam urutan acak".
Joël

Jawaban:

112

Mungkin tidak diurutkan sama sekali dan menggunakan urutan entri muncul di sistem file, yaitu yang Anda dapatkan saat menggunakan ls -U. (Setidaknya pada mesin saya ini menghasilkan urutan yang sama dengan daftar globpencocokan).

Xion
sumber
1
Ya, kecuali itu melakukan upaya khusus, itu hanya akan menampilkan entri sebagai sistem operasi menyediakannya. Sama seperti perintah "find" di Unix, ia hanya membuang entri sesuai urutannya dari struktur data yang digunakan oleh sistem file yang mendasarinya. Anda tidak boleh membuat asumsi apa pun tentang pemesanannya, bahkan jika Anda akan melihat bahwa file-file tersebut tampaknya muncul dalam urutan pembuatan.
Raúl Salinas-Monteagudo
421

Pesanan sewenang-wenang, tetapi Anda dapat mengurutkannya sendiri

Jika Anda ingin disortir berdasarkan nama:

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

diurutkan berdasarkan waktu modifikasi:

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

diurutkan berdasarkan ukuran:

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

dll.

John La Rooy
sumber
1
Saya memiliki file, di mana nama hanya bilangan bulat, tanpa ekstensi, jadi saya menggunakan: files = glob.glob('teksty/*'). Akankah pesanan dengan nam diberikan?
andilabs
3
@mgalgs Tidak, itu bukan pertanyaan yang ingin saya tanyakan. Apa yang ingin saya ketahui dijawab oleh Xion.
Martin Thoma
Dan bagaimana dengan mengurutkannya berdasarkan tanggal pembuatan tetapi sesuai dengan waktu pembuatan. Karena itu daftar saya pertama file pendatang baru. Bagaimana saya bisa mendapatkan daftar dari file lama ke file baru? Terima kasih!
joaquindev
1
Perhatikan bahwa getmtime dan getsize relatif mahal - melakukan ini untuk banyak file mungkin memakan waktu ..
drevicko
53

Dengan memeriksa kode sumber glob.globAnda melihat bahwa itu panggilan internal os.listdir, dijelaskan di sini:

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

Kalimat kunci: os.listdir (path) Mengembalikan daftar yang berisi nama-nama entri dalam direktori yang diberikan oleh path. Daftar ini dalam urutan acak. Itu tidak termasuk entri khusus '.' dan '..' bahkan jika mereka ada di direktori.

Pesanan sewenang-wenang . :)

Ray Toal
sumber
14

glob.glob () adalah pembungkus di sekitar os.listdir () sehingga OS yang mendasari bertanggung jawab untuk mengirimkan data. Secara umum: Anda tidak dapat membuat asumsi tentang pemesanan di sini. Asumsi dasarnya adalah: tidak ada pemesanan. Jika Anda memerlukan penyortiran: sortir pada level aplikasi.

Andreas Jung
sumber
13

Pesanan sewenang-wenang, tetapi ada beberapa cara untuk mengurutkannya. Salah satunya adalah sebagai berikut:

#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]))
April
sumber
Apa kontribusi jawaban Anda dibandingkan dengan jawaban yang ada?
Martin Thoma
2
@ MartinThoma Saya memiliki masalah dengan diurutkan tidak mengurutkan nama file jika bilangan bulat yang ada di file tidak nol empuk. Penyortiran dimulai pada 1000, naik ke apa pun bilangan bulat tertinggi dan kemudian mulai kembali dari bilangan bulat terkecil. Jika saya nol pad angkanya, hanya memanggil diurutkan pada file mengurutkannya dengan sempurna. Jadi saya pikir solusi ini menyelesaikan masalah ketika disortir saja tidak berfungsi.
Will.Evo
1
@ Will.Evo Coba gunakan natsort: from natsort import natsorted; files = natsorted(files).
Martin Thoma
Jawaban Anda membantu!
Vineet
12

Saya memiliki masalah yang sama, globmengembalikan daftar nama file dalam urutan acak tetapi saya ingin melangkah melalui urutan numerik seperti yang ditunjukkan oleh nama file. Beginilah cara saya mencapainya:

File saya dikembalikan oleh globsesuatu seperti:

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

Saya mengurutkan daftar di tempat, untuk melakukan ini saya membuat fungsi:

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

Fungsi ini mengembalikan bagian numerik dari nama file dan mengkonversi ke integer. Saya kemudian memanggil metode sortir dalam daftar sebagai berikut:

myList.sort(key=sortKeyFunc)

Ini mengembalikan daftar sebagai berikut:

["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
sumber
Saya pikir ini lebih elegan untuk digunakan os.path.splitext(os.path.basename(s))[0]daripada os.path.basename(s)[:-4], jadi definisi fungsi akan menjadi. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit
1

Jika Anda bertanya-tanya tentang apa yang dilakukan glob.glob pada sistem Anda di masa lalu dan tidak dapat menambahkan sortedpanggilan, pemesanan akan konsisten pada sistem file Mac HFS + dan akan menjadi urutan traversal pada sistem Unix lainnya. Jadi kemungkinan besar akan menjadi deterministik kecuali sistem file yang mendasarinya ditata ulang yang dapat terjadi jika file ditambahkan, dihapus, diganti nama, dihapus, dipindahkan, dll ...

crizCraig
sumber
Bagaimana dengan APFS di macOS?
Boris
0

Dari solusi @Johan La Rooy, memilah gambar menggunakan sorted(glob.glob('*.png'))tidak berfungsi untuk saya, daftar output masih tidak diurutkan dengan nama mereka.

Namun, sorted(glob.glob('*.png'), key=os.path.getmtime)kerjanya dengan sempurna.

Saya agak bingung bagaimana bisa menyortir berdasarkan nama mereka tidak berfungsi di sini.

Terima kasih @Martin Thoma karena memposting pertanyaan hebat ini dan @Johan La Rooy untuk solusi yang bermanfaat.

Haoyu Wang
sumber
-1

Silakan coba kode ini:

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

Begitulah cara saya melakukan kasus khusus saya. Semoga bermanfaat.

Elizabeth
sumber
1
Anda harus mengubah jawaban Anda agar sesuai dengan pertanyaan.
CodenameLambda
1
Pertanyaannya bukan tentang penyortiran. Saya tahu (dan saya tahu saat itu) bagaimana cara menyortir. Pertanyaannya adalah tentang urutan default.
Martin Thoma
1
Terima kasih atas cuplikan kode ini, yang dapat memberikan bantuan segera. Penjelasan yang tepat akan sangat meningkatkan nilai pendidikannya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat bagi pembaca masa depan dengan pertanyaan yang serupa, tetapi tidak sama. Harap edit jawaban Anda untuk menambahkan penjelasan, dan berikan indikasi batasan dan asumsi apa yang berlaku.
Toby Speight