Wie erhalten Sie eine Verzeichnisliste, die in Python nach Erstellungsdatum sortiert ist?

129

Was ist der beste Weg, um eine Liste aller Dateien in einem Verzeichnis zu erhalten, sortiert nach Datum [Erstellt | geändert], mit Python, auf einem Windows-Computer?

Liza
quelle

Antworten:

79

Update : um dirpathdie Einträge nach Änderungsdatum in Python 3 zu sortieren :

import os
from pathlib import Path

paths = sorted(Path(dirpath).iterdir(), key=os.path.getmtime)

( Geben Sie hier die Antwort von @ Pygirl ein , um die Sichtbarkeit zu verbessern. )

Wenn Sie bereits eine Liste mit Dateinamen haben files, können Sie diese nach Erstellungszeit unter Windows sortieren:

files.sort(key=os.path.getctime)

Die Liste der Dateien, die Sie beispielsweise verwenden können, globwie in @ Jays Antwort gezeigt .


alte Antwort Hier ist eine ausführlichere Version der @Greg HewgillAntwort . Es entspricht am ehesten den Anforderungen der Frage. Es wird zwischen Erstellungs- und Änderungsdaten unterschieden (zumindest unter Windows).

#!/usr/bin/env python
from stat import S_ISREG, ST_CTIME, ST_MODE
import os, sys, time

# path to the directory (relative or absolute)
dirpath = sys.argv[1] if len(sys.argv) == 2 else r'.'

# get all entries in the directory w/ stats
entries = (os.path.join(dirpath, fn) for fn in os.listdir(dirpath))
entries = ((os.stat(path), path) for path in entries)

# leave only regular files, insert creation date
entries = ((stat[ST_CTIME], path)
           for stat, path in entries if S_ISREG(stat[ST_MODE]))
#NOTE: on Windows `ST_CTIME` is a creation date 
#  but on Unix it could be something else
#NOTE: use `ST_MTIME` to sort by a modification date

for cdate, path in sorted(entries):
    print time.ctime(cdate), os.path.basename(path)

Beispiel:

$ python stat_creation_date.py
Thu Feb 11 13:31:07 2009 stat_creation_date.py
jfs
quelle
1
Das hat perfekt funktioniert. Ich versuche, zwei Verzeichnisse cdate miteinander zu vergleichen. Gibt es eine Möglichkeit, die Sekunden zwischen den beiden Daten zu vergleichen?
Federer
@malcmcmul: cdateist eine Float-Anzahl von Sekunden seit Epoche.
JFS
4
Dies funktioniert, aber die prägnanteste Lösung finden Sie unter stackoverflow.com/a/4500607/68534
jmoz
@jmoz: meinst du so . Die Lösung, die Sie verknüpfen, ist falsch: Sie filtert keine regulären Dateien. Hinweis: Meine Lösung ruft stateinmal pro Verzeichniseintrag auf.
JFS
Verzeih mir, der von Sabastian bereitgestellte Link ist noch prägnanter! Danke dir.
jmoz
148

Ich habe dies in der Vergangenheit für ein Python-Skript getan, um die zuletzt aktualisierten Dateien in einem Verzeichnis zu ermitteln:

import glob
import os

search_dir = "/mydir/"
# remove anything from the list that is not a file (directories, symlinks)
# thanks to J.F. Sebastion for pointing out that the requirement was a list 
# of files (presumably not including directories)  
files = list(filter(os.path.isfile, glob.glob(search_dir + "*")))
files.sort(key=lambda x: os.path.getmtime(x))

Das sollte das tun, wonach Sie suchen, basierend auf der Datei mtime.

BEARBEITEN : Beachten Sie, dass Sie bei Bedarf auch os.listdir () anstelle von glob.glob () verwenden können. Der Grund, warum ich glob in meinem ursprünglichen Code verwendet habe, war, dass ich glob verwenden wollte, um nur nach Dateien mit einem bestimmten Satz zu suchen von Dateierweiterungen, für die glob () besser geeignet war. Um listdir zu verwenden, würde es folgendermaßen aussehen:

import os

search_dir = "/mydir/"
os.chdir(search_dir)
files = filter(os.path.isfile, os.listdir(search_dir))
files = [os.path.join(search_dir, f) for f in files] # add path to each file
files.sort(key=lambda x: os.path.getmtime(x))
Jay
quelle
glob () ist nett, aber denken Sie daran, dass es Dateien überspringt, die mit einem Punkt beginnen. * nix-Systeme behandeln solche Dateien als versteckt (wodurch sie in den Listen weggelassen werden), aber in Windows sind sie normale Dateien.
Efotinis
Diese Lösungen schließen Verzeichnisse nicht von der Liste aus.
Constantin
In Ihrer os.listdir-Lösung fehlt die Datei os.path.join: files.sort (Lambda x, y: cmp (os.path.getmtime (os.path.join (search_dir, x)), os.path.getmtime (os) .path.join (search_dir, y))))
Peter Hoffmann
files.sort(key=lambda fn: os.path.getmtime(os.path.join(search_dir, fn)))
JFS
22
Ein bloßes files.sort(key=os.path.getmtime)sollte funktionieren (ohne lambda).
JFS
31

Es gibt eine os.path.getmtimeFunktion, die die Anzahl der Sekunden seit der Epoche angibt und schneller sein sollte als os.stat.

import os 

os.chdir(directory)
sorted(filter(os.path.isfile, os.listdir('.')), key=os.path.getmtime)
Gypaetus
quelle
23

Hier ist meine Version:

def getfiles(dirpath):
    a = [s for s in os.listdir(dirpath)
         if os.path.isfile(os.path.join(dirpath, s))]
    a.sort(key=lambda s: os.path.getmtime(os.path.join(dirpath, s)))
    return a

Zuerst erstellen wir eine Liste der Dateinamen. isfile () wird verwendet, um Verzeichnisse zu überspringen. Es kann weggelassen werden, wenn Verzeichnisse enthalten sein sollten. Anschließend sortieren wir die Liste direkt und verwenden das Änderungsdatum als Schlüssel.

efotinis
quelle
Es sortierte es nach dem ältesten zuerst bis zum neuesten. Als ich die 5 neuesten Dateien wollte, musste ich Folgendes tuna[-5:]
Daniel Butler
20

Hier ist ein Einzeiler:

import os
import time
from pprint import pprint

pprint([(x[0], time.ctime(x[1].st_ctime)) for x in sorted([(fn, os.stat(fn)) for fn in os.listdir(".")], key = lambda x: x[1].st_ctime)])

Dies ruft os.listdir () auf, um eine Liste der Dateinamen abzurufen, ruft dann os.stat () auf, um die Erstellungszeit abzurufen, und sortiert dann nach der Erstellungszeit.

Beachten Sie, dass diese Methode os.stat () für jede Datei nur einmal aufruft. Dies ist effizienter als das Aufrufen für jeden Vergleich in einer Sortierung.

Greg Hewgill
quelle
Das ist kaum pythonisch, obwohl es den Job löst (Haftungsausschluss: Code nicht getestet).
Adriano Varoli Piazza
Diese Lösung schließt Verzeichnisse nicht von der Liste aus.
Constantin
@Constantin: das stimmt, aber ein kurzer [... wenn stat.S_ISREG (x)] damit umgehen würde.
Greg Hewgill
16

Ohne das Verzeichnis zu wechseln:

import os    

path = '/path/to/files/'
name_list = os.listdir(path)
full_list = [os.path.join(path,i) for i in name_list]
time_sorted_list = sorted(full_list, key=os.path.getmtime)

print time_sorted_list

# if you want just the filenames sorted, simply remove the dir from each
sorted_filename_list = [ os.path.basename(i) for i in time_sorted_list]
print sorted_filename_list
Nic
quelle
12

In Python 3.5+

from pathlib import Path
sorted(Path('.').iterdir(), key=lambda f: f.stat().st_mtime)
ignorant
quelle
3
Verwenden Sie f.stat().st_ctimestattdessen das Erstellungsdatum .
Alanjds
11

Hier ist meine Antwort mit glob ohne Filter, wenn Sie Dateien mit einer bestimmten Erweiterung in Datumsreihenfolge lesen möchten (Python 3).

dataset_path='/mydir/'   
files = glob.glob(dataset_path+"/morepath/*.extension")   
files.sort(key=os.path.getmtime)
dinos66
quelle
5
# *** the shortest and best way ***
# getmtime --> sort by modified time
# getctime --> sort by created time

import glob,os

lst_files = glob.glob("*.txt")
lst_files.sort(key=os.path.getmtime)
print("\n".join(lst_files))
Arash
quelle
Bitte geben Sie den Kontext an
Claire
"am besten" ist subjektiv. Ihre Antwort wäre besser, wenn Sie erklären würden, warum Sie denken, dass dies der beste Weg ist.
Bryan Oakley
Wenn Sie "das Beste" wollen, verwenden Sie Glob sicherlich nicht, da es sehr langsam ist.
user136036
4
sorted(filter(os.path.isfile, os.listdir('.')), 
    key=lambda p: os.stat(p).st_mtime)

Sie könnten verwenden, os.walk('.').next()[-1]anstatt mit zu filtern os.path.isfile, aber das lässt tote Symlinks in der Liste und os.statschlägt bei ihnen fehl.

Alex Coventry
quelle
4
from pathlib import Path
import os

sorted(Path('./').iterdir(), key=lambda t: t.stat().st_mtime)

oder

sorted(Path('./').iterdir(), key=os.path.getmtime)

oder

sorted(os.scandir('./'), key=lambda t: t.stat().st_mtime)

Dabei ist m Zeit die geänderte Zeit.

Pygirl
quelle
1

Dies ist ein grundlegender Schritt zum Lernen:

import os, stat, sys
import time

dirpath = sys.argv[1] if len(sys.argv) == 2 else r'.'

listdir = os.listdir(dirpath)

for i in listdir:
    os.chdir(dirpath)
    data_001 = os.path.realpath(i)
    listdir_stat1 = os.stat(data_001)
    listdir_stat2 = ((os.stat(data_001), data_001))
    print time.ctime(listdir_stat1.st_ctime), data_001
cumulus_13
quelle
1

Die Antwort von Alex Coventry führt zu einer Ausnahme, wenn die Datei ein Symlink zu einer nicht vorhandenen Datei ist. Der folgende Code korrigiert diese Antwort:

import time
import datetime
sorted(filter(os.path.isfile, os.listdir('.')), 
    key=lambda p: os.path.exists(p) and os.stat(p).st_mtime or time.mktime(datetime.now().timetuple())

Wenn die Datei nicht vorhanden ist, wird now () verwendet und der Symlink wird ganz am Ende der Liste angezeigt.

Paolo Benvenuto
quelle
0

Hier ist ein einfaches paar Zeilen, die nach Erweiterung suchen und eine Sortieroption bieten

def get_sorted_files(src_dir, regex_ext='*', sort_reverse=False): 
    files_to_evaluate = [os.path.join(src_dir, f) for f in os.listdir(src_dir) if re.search(r'.*\.({})$'.format(regex_ext), f)]
    files_to_evaluate.sort(key=os.path.getmtime, reverse=sort_reverse)
    return files_to_evaluate
TXN_747
quelle
0

Der Vollständigkeit os.scandirhalber mit (2x schneller pathlib):

import os
sorted(os.scandir('/tmp/test'), key=lambda d: d.stat().st_mtime)
n1nj4
quelle
0

Das war meine Version:

import os

folder_path = r'D:\Movies\extra\new\dramas' # your path
os.chdir(folder_path) # make the path active
x = sorted(os.listdir(), key=os.path.getctime)  # sorted using creation time

folder = 0

for folder in range(len(x)):
    print(x[folder]) # print all the foldername inside the folder_path
    folder = +1
haqrafiul
quelle
In meinem Code sind die Dateien als älteste bis neueste sortiert. Um die neuesten Dateinamen oder Ordner zuerst zu erhalten, müssen Sie reverse = True in die Dateiliste einfügen (in meinem Fall war es x). Also, x = sortiert (os.listdir (), key = os.path.getctime, reverse = True)
haqrafiul
-6

Vielleicht sollten Sie Shell-Befehle verwenden. Unter Unix / Linux kann find piped with sort wahrscheinlich das tun, was Sie wollen.

stephanea
quelle