Come si ottiene un elenco di directory ordinato per data di creazione in Python?


129

Qual è il modo migliore per ottenere un elenco di tutti i file in una directory, ordinati per data [creato | modificato], usando Python, su una macchina Windows?

Risposte:


79

Aggiornamento : per ordinare dirpathle voci in base alla data di modifica in Python 3:

import os
from pathlib import Path

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

(inserisci qui la risposta di @ Pygirl per una maggiore visibilità)

Se hai già un elenco di nomi di file files, per ordinarlo sul posto al momento della creazione su Windows:

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

L'elenco dei file che potresti ottenere, ad esempio, usando globcome mostrato nella risposta di @ Jay .


vecchia risposta Ecco una versione più dettagliata della @Greg Hewgillrisposta . È il più conforme ai requisiti della domanda. Fa una distinzione tra le date di creazione e modifica (almeno su 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)

Esempio:

$ python stat_creation_date.py
Thu Feb 11 13:31:07 2009 stat_creation_date.py

1
Questo ha funzionato perfettamente. Sto cercando di confrontare due directory cdate tra loro. C'è un modo per confrontare i secondi tra i due cdate?
Federer,

@malcmcmul: cdateè un numero float di secondi dall'epoca.
jfs,

4
Questo funziona, ma la soluzione più succinta è al stackoverflow.com/a/4500607/68534
jmoz

@jmoz: vuoi dire come questo . La soluzione che hai collegato è sbagliata: non filtra i file normali. Nota: la mia soluzione chiama statuna volta per dir.entry.
jfs,

Perdonami, il link fornito da Sabastian è ancora più conciso! Grazie.
jmoz,

148

L'ho fatto in passato per uno script Python per determinare gli ultimi file aggiornati in una directory:

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))

Questo dovrebbe fare quello che stai cercando in base al file mtime.

EDIT : Nota che puoi anche usare os.listdir () al posto di glob.glob () se lo desideri - il motivo per cui ho usato glob nel mio codice originale era che volevo usare glob per cercare solo file con un determinato set delle estensioni di file, a cui glob () era più adatto. Per usare listdir ecco come sarebbe:

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))

glob () è carino, ma tieni presente che salta i file a partire da un punto. * I sistemi nix trattano tali file come nascosti (omettendoli così dagli elenchi), ma in Windows sono file normali.
efotinis,

Queste soluzioni non escludono le directory dall'elenco.
Constantin,

Nella tua soluzione os.listdir manca 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
Un semplice files.sort(key=os.path.getmtime)dovrebbe funzionare (senza lambda).
jfs,

31

C'è una os.path.getmtimefunzione che fornisce il numero di secondi dall'epoca e dovrebbe essere più veloce di os.stat.

import os 

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

23

Ecco la mia versione:

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

Innanzitutto, costruiamo un elenco dei nomi dei file. isfile () è usato per saltare le directory; può essere omesso se si devono includere le directory. Quindi, ordiniamo l'elenco sul posto, usando la data di modifica come chiave.


Lo ordinò dal più vecchio al più recente. Quando volevo i 5 file più recenti dovevo fare quanto seguea[-5:]
Daniel Butler,

20

Ecco un one-liner:

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

Questo chiama os.listdir () per ottenere un elenco dei nomi dei file, quindi chiama os.stat () per ognuno per ottenere il tempo di creazione, quindi ordina in base al tempo di creazione.

Si noti che questo metodo chiama os.stat () solo una volta per ciascun file, il che sarà più efficiente rispetto a chiamarlo per ogni confronto in un ordinamento.


non è molto pitonico, sebbene risolva il lavoro (dichiarazione di non responsabilità: non ho testato il codice).
Adriano Varoli Piazza

Questa soluzione non esclude le directory dall'elenco.
Constantin,

@Constantin: è vero, ma un rapido [... se stat.S_ISREG (x)] lo gestirà.
Greg Hewgill,

16

Senza cambiare directory:

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

12

In Python 3.5+

from pathlib import Path
sorted(Path('.').iterdir(), key=lambda f: f.stat().st_mtime)

3
per la data di creazione, utilizzare f.stat().st_ctimeinvece.
Alanjds,

11

Ecco la mia risposta usando glob senza filtro se vuoi leggere i file con una certa estensione in ordine di data (Python 3).

dataset_path='/mydir/'   
files = glob.glob(dataset_path+"/morepath/*.extension")   
files.sort(key=os.path.getmtime)

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))

si prega di fornire contesto
Claire

"migliore" è soggettivo. La tua risposta sarebbe migliore se spiegassi perché pensi che sia il modo migliore.
Bryan Oakley,

Se vuoi "il meglio", sicuramente non usi glob, poiché è molto lento.
user136036

4
sorted(filter(os.path.isfile, os.listdir('.')), 
    key=lambda p: os.stat(p).st_mtime)

È possibile utilizzare os.walk('.').next()[-1]invece di filtrare con os.path.isfile, ma ciò lascia collegamenti simbolici morti nell'elenco e os.statfallirà su di essi.


4
from pathlib import Path
import os

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

o

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

o

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

dove m è il tempo modificato.


1

questo è un passo fondamentale per imparare:

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

1

La risposta di Alex Coventry produrrà un'eccezione se il file è un link simbolico a un file inesistente, il seguente codice corregge quella risposta:

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())

Quando il file non esiste, viene utilizzato now () e il collegamento simbolico andrà alla fine dell'elenco.


0

Ecco una semplice coppia di righe che cerca l'estensione e fornisce un'opzione di ordinamento

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

0

Per completezza con os.scandir(2x più veloce pathlib):

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

0

Questa era la mia versione:

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

Nel mio codice i file sono ordinati dal più vecchio al più recente. Per ottenere prima i nomi dei file o le cartelle più recenti, è necessario aggiungere reverse = True nell'elenco dei file (nel mio caso era x). così, x = ordinato (os.listdir (), chiave = os.path.getctime, reverse = True)
haqrafiul

-6

Forse dovresti usare i comandi di shell. In Unix / Linux, trovare il piping con sort sarà probabilmente in grado di fare quello che vuoi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.