Wie wird Pythons glob.glob bestellt?

199

Ich habe den folgenden Python-Code geschrieben:

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

Jetzt verstehe ich das:

/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

Wie wird es bestellt?

Es könnte Ihnen helfen, meine ls-l-Ausgabe zu erhalten:

-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

Es ist nicht nach Dateiname oder Größe sortiert.

Andere Links: glob,ls

Martin Thoma
quelle
2
Die endgültige Antwort scheint zu sein, dass der lsBefehl selbst Dateien nach Namen sortiert. 'ls -U' gibt eine ungeordnete Liste von Dateien in "Verzeichnisreihenfolge" an.
Brian Peterson
2
Unter Windows wurde es sortiert, also habe ich einfach angenommen, dass es immer so ist. Unter Ubuntu hat es mich das Debuggen gekostet. Hinweis für sich selbst - lesen Sie die API! : 0)
Yuri Feldman
Das Verhalten ist dasselbe mit os.listdir: * nix OS gibt Dateien in einer nicht alphabetischen Reihenfolge zurück, und (schade, dass ich überrascht bin!) Dies wird in der Dokumentation explizit angegeben : "Die Liste ist in beliebiger Reihenfolge".
Joël

Antworten:

112

Es ist wahrscheinlich überhaupt nicht sortiert und verwendet die Reihenfolge, in der Einträge im Dateisystem angezeigt werden, dh die, die Sie bei der Verwendung erhalten ls -U. (Zumindest auf meinem Computer ergibt dies die gleiche Reihenfolge wie das Auflisten von globÜbereinstimmungen).

Xion
quelle
1
Ja, sofern keine besonderen Anstrengungen unternommen werden, werden die Einträge einfach so angezeigt, wie sie vom Betriebssystem bereitgestellt werden. Wie der Befehl "find" unter Unix werden die Einträge nur in der Reihenfolge ausgegeben, in der sie aus der vom zugrunde liegenden Dateisystem verwendeten Datenstruktur stammen. Sie sollten keine Annahmen über die Reihenfolge treffen, selbst wenn Sie sehen würden, dass Dateien in der Erstellungsreihenfolge angezeigt werden.
Raúl Salinas-Monteagudo
421

Die Reihenfolge ist beliebig, aber Sie können sie selbst sortieren

Wenn Sie nach Namen sortiert werden möchten:

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

sortiert nach Änderungszeit:

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

sortiert nach Größe:

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

etc.

John La Rooy
quelle
1
Ich habe Dateien, bei denen Namen nur Ganzzahlen sind, ohne Erweiterung, daher verwende ich : files = glob.glob('teksty/*'). Wird der Auftrag von nam erteilt?
Andilabs
3
@mgalgs Nein, das war nicht die Frage, die ich wirklich stellen wollte. Was ich wissen wollte, wurde von Xion beantwortet.
Martin Thoma
Und was ist mit dem Sortieren nach Erstellungsdatum, aber nach Erstellungszeit. Weil es mir zuerst die neuesten Dateien auflistet. Wie kann ich eine Liste von alten zu neuesten Dateien erhalten? Danke dir!
Joaquindev
1
Beachten Sie, dass getmtime und getize relativ teuer sind - dies für viele Dateien kann eine Weile dauern ..
drevicko
53

Indem Sie den Quellcode von überprüfen glob.glob, sehen Sie, dass er intern aufruft os.listdir, wie hier beschrieben:

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

Schlüsselsatz: os.listdir (Pfad) Gibt eine Liste zurück, die die Namen der Einträge in dem durch path angegebenen Verzeichnis enthält. Die Liste ist in beliebiger Reihenfolge. Die Sondereinträge '.' Sind nicht enthalten. und '..' auch wenn sie im Verzeichnis vorhanden sind.

Beliebige Reihenfolge . :) :)

Ray Toal
quelle
14

glob.glob () ist ein Wrapper um os.listdir (), sodass das zugrunde liegende Betriebssystem für die Bereitstellung der Daten verantwortlich ist. Generell: Sie können hier keine Annahme über die Bestellung machen. Die Grundannahme lautet: keine Bestellung. Wenn Sie eine Sortierung benötigen: Sortieren Sie auf Anwendungsebene.

Andreas Jung
quelle
13

Die Reihenfolge ist willkürlich, aber es gibt verschiedene Möglichkeiten, sie zu sortieren. Eine davon ist wie folgt:

#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
quelle
Was trägt Ihre Antwort im Vergleich zu den vorhandenen Antworten bei?
Martin Thoma
2
@MartinThoma Ich habe ein Problem damit, die Dateinamen nicht zu sortieren, wenn die in den Dateien vorhandenen Ganzzahlen nicht mit Nullen aufgefüllt sind. Die Sortierung beginnt bei 1000, geht bis zu der höchsten Ganzzahl und beginnt dann wieder bei der kleinsten Ganzzahl. Wenn ich die Zahlen auf Null stelle, werden sie durch einfaches Aufrufen der sortierten Dateien perfekt sortiert. Ich denke, diese Lösung löst das Problem, wenn die Sortierung alleine nicht funktioniert.
Will.Evo
@ Will.Evo Versuchen Sie es mit natsort: from natsort import natsorted; files = natsorted(files).
Martin Thoma
Ihre Antwort hat geholfen!
Vineet
12

Ich hatte ein ähnliches Problem, glob gab eine Liste von Dateinamen in einer beliebigen Reihenfolge zurück, wollte sie jedoch in numerischer Reihenfolge durchgehen, wie durch den Dateinamen angegeben. So habe ich es erreicht:

Meine Dateien wurden zurückgegeben von 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"]

Ich habe die Liste sortiert, dazu habe ich eine Funktion erstellt:

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

Diese Funktion gibt den numerischen Teil des Dateinamens zurück und konvertiert in eine Ganzzahl. Ich habe dann die Sortiermethode in der Liste als solche aufgerufen:

myList.sort(key=sortKeyFunc)

Dies gab eine Liste als solche zurück:

["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
quelle
Ich denke, es ist eleganter zu verwenden os.path.splitext(os.path.basename(s))[0]als os.path.basename(s)[:-4], also wird die Funktionsdefinition sein. def sortKeyFunc(s): return int(os.path.splitext(os.path.basename(s))[0])
ePandit
1

Wenn Sie sich fragen, was glob.glob in der Vergangenheit auf Ihrem System getan hat und keinen sortedAnruf hinzufügen kann , ist die Reihenfolge auf Mac HFS + -Dateisystemen konsistent und auf anderen Unix-Systemen die Durchlaufreihenfolge . Es wird also wahrscheinlich deterministisch gewesen sein, wenn das zugrunde liegende Dateisystem nicht neu organisiert wurde. Dies kann passieren, wenn Dateien hinzugefügt, entfernt, umbenannt, gelöscht, verschoben usw. werden.

crizCraig
quelle
Was ist mit APFS unter macOS?
Boris
0

Aus der Lösung von @Johan La Rooy, Sortieren der Bilder mit sorted(glob.glob('*.png')) nicht für mich. Die Ausgabeliste ist immer noch nicht nach Namen geordnet.

Die sorted(glob.glob('*.png'), key=os.path.getmtime) funktioniert aber perfekt.

Ich bin etwas verwirrt, wie das Sortieren nach Namen hier nicht funktioniert.

Vielen Dank an @Martin Thoma für die Veröffentlichung dieser großartigen Frage und an @Johan La Rooy für die hilfreichen Lösungen.

Haoyu Wang
quelle
-1

Bitte versuchen Sie diesen Code:

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

So habe ich meinen speziellen Fall gemacht. Hoffe es ist hilfreich.

Elisabeth
quelle
1
Sie sollten Ihre Antwort an die Frage anpassen.
CodenameLambda
1
Die Frage ist nicht über das Sortieren. Ich weiß (und ich wusste damals), wie man sortiert. Die Frage bezieht sich auf die Standardreihenfolge.
Martin Thoma
1
Vielen Dank für dieses Code-Snippet, das möglicherweise sofortige Hilfe bietet. Eine richtige Erklärung würde den Bildungswert erheblich verbessern , indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und sie für zukünftige Leser mit ähnlichen, aber nicht identischen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, und geben Sie an, welche Einschränkungen und Annahmen gelten.
Toby Speight