Jak uzyskać listę katalogów posortowaną według daty utworzenia w Pythonie?

129

Jaki jest najlepszy sposób uzyskania listy wszystkich plików w katalogu, posortowanych według daty [utworzono | zmodyfikowano], używając języka Python, na komputerze z systemem Windows?

Liza
źródło

Odpowiedzi:

79

Aktualizacja : aby posortować dirpathwpisy według daty modyfikacji w Pythonie 3:

import os
from pathlib import Path

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

(wstaw odpowiedź @ Pygirl tutaj, aby uzyskać lepszą widoczność)

Jeśli masz już listę nazw plików files, posortuj ją według czasu utworzenia w systemie Windows:

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

Lista plików, które możesz uzyskać, na przykład, używając, globjak pokazano w odpowiedzi @ Jaya .


stara odpowiedź Oto bardziej szczegółowa wersja @Greg Hewgillodpowiedzi . Jest to najbardziej zgodne z wymaganiami pytania. Wprowadza rozróżnienie między datami utworzenia i modyfikacji (przynajmniej w systemie 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)

Przykład:

$ python stat_creation_date.py
Thu Feb 11 13:31:07 2009 stat_creation_date.py
jfs
źródło
1
To działało doskonale. Próbuję porównać ze sobą dwa katalogi cdate. Czy jest sposób na porównanie sekund między dwoma płytami CD?
Federer
@malcmcmul: cdateto zmiennoprzecinkowa liczba sekund od epoki.
jfs
4
To działa, ale najbardziej zwięzłe rozwiązanie znajduje się na stackoverflow.com/a/4500607/68534
jmoz
@jmoz: czy masz na myśli to . Rozwiązanie, do którego odsyłasz, jest nieprawidłowe: nie filtruje zwykłych plików. Uwaga: moje rozwiązanie wywołuje statjeden raz w każdym katalogu.
jfs
Wybaczcie, link podany przez Sabastiana jest jeszcze bardziej zwięzły! Dziękuję Ci.
jmoz
148

Robiłem to w przeszłości dla skryptu Pythona do określenia ostatnich zaktualizowanych plików w katalogu:

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

To powinno zrobić to, czego szukasz, na podstawie pliku mtime.

EDYCJA : Zauważ, że możesz również użyć os.listdir () zamiast glob.glob () w razie potrzeby - powodem, dla którego użyłem glob w moim oryginalnym kodzie, było to, że chciałem użyć glob do wyszukiwania tylko plików z określonym zestawem rozszerzeń plików, do których lepiej pasowała funkcja glob (). Aby użyć listdir, oto jak by to wyglądało:

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))
Sójka
źródło
glob () jest fajne, ale pamiętaj, że pomija pliki zaczynające się od kropki. Systemy * nix traktują takie pliki jako ukryte (pomijając je w ten sposób na liście), ale w systemie Windows są to zwykłe pliki.
efotinis
Te rozwiązania nie wykluczają książek z listy.
Constantin
W rozwiązaniu os.listdir brakuje pliku 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
Zwykły files.sort(key=os.path.getmtime)powinien działać (bez lambda).
jfs
31

Istnieje os.path.getmtimefunkcja, która podaje liczbę sekund od epoki i powinna być szybsza niż os.stat.

import os 

os.chdir(directory)
sorted(filter(os.path.isfile, os.listdir('.')), key=os.path.getmtime)
gypaetus
źródło
23

Oto moja wersja:

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

Najpierw tworzymy listę nazw plików. isfile () służy do pomijania katalogów; można go pominąć, jeśli mają być uwzględnione katalogi. Następnie sortujemy listę lokalnie, używając daty modyfikacji jako klucza.

efotinis
źródło
Posortował je od najstarszego do najnowszego. Kiedy chciałem mieć 5 najnowszych plików, musiałem zrobić co następujea[-5:]
Daniel Butler
20

Oto jedna linijka:

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

To wywołuje os.listdir (), aby uzyskać listę nazw plików, a następnie wywołuje os.stat () dla każdego z nich, aby uzyskać czas utworzenia, a następnie sortuje w odniesieniu do czasu utworzenia.

Zauważ, że ta metoda wywołuje os.stat () tylko raz dla każdego pliku, co będzie bardziej wydajne niż wywoływanie jej dla każdego porównania w sortowaniu.

Greg Hewgill
źródło
to nie jest Pythonowe, chociaż rozwiązuje zadanie (zastrzeżenie: nie testowałem kodu).
Adriano Varoli Piazza
To rozwiązanie nie wyklucza książek z listy.
Constantin,
@Constantin: to prawda, ale szybkie [... jeśli stat.S_ISREG (x)] poradzi sobie z tym.
Greg Hewgill
16

Bez zmiany katalogu:

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
źródło
12

W Pythonie 3.5+

from pathlib import Path
sorted(Path('.').iterdir(), key=lambda f: f.stat().st_mtime)
nieświadomy
źródło
3
f.stat().st_ctimezamiast daty utworzenia użyj .
alanjds
11

Oto moja odpowiedź przy użyciu globu bez filtra, jeśli chcesz czytać pliki z określonym rozszerzeniem w kolejności dat (Python 3).

dataset_path='/mydir/'   
files = glob.glob(dataset_path+"/morepath/*.extension")   
files.sort(key=os.path.getmtime)
dinos66
źródło
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))
Wysypka
źródło
proszę podać kontekst
Claire,
„najlepsze” jest subiektywne. Twoja odpowiedź byłaby lepsza, gdybyś wyjaśnił, dlaczego uważasz, że to najlepszy sposób.
Bryan Oakley
Jeśli chcesz „najlepszego”, na pewno nie używasz globu, ponieważ jest bardzo wolny.
user136036
4
sorted(filter(os.path.isfile, os.listdir('.')), 
    key=lambda p: os.stat(p).st_mtime)

Możesz użyć os.walk('.').next()[-1]zamiast filtrowania z os.path.isfile, ale to pozostawia martwe dowiązania symboliczne na liście i os.statzawiedzie na nich.

Alex Coventry
źródło
4
from pathlib import Path
import os

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

lub

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

lub

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

gdzie m czas jest czasem zmodyfikowanym.

Pygirl
źródło
1

to jest podstawowy krok do nauki:

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
źródło
1

Odpowiedź Alexa Coventry'ego spowoduje wyjątek, jeśli plik jest dowiązaniem symbolicznym do nieistniejącego pliku, poniższy kod poprawia tę odpowiedź:

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

Gdy plik nie istnieje, używana jest funkcja now (), a dowiązanie symboliczne zostanie umieszczone na samym końcu listy.

Paolo Benvenuto
źródło
0

Oto kilka prostych linii, które szukają rozszerzenia, a także zapewniają opcję sortowania

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
źródło
0

Aby uzyskać kompletność z os.scandir(2x szybciej pathlib):

import os
sorted(os.scandir('/tmp/test'), key=lambda d: d.stat().st_mtime)
n1nj4
źródło
0

To była moja wersja:

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
źródło
W moim kodzie pliki są sortowane od najstarszych do najnowszych. Aby najpierw pobrać najnowsze nazwy plików lub folderów, musisz dodać reverse = True na liście plików (w moim przypadku było to x). tak, x = sortowane (os.listdir (), key = os.path.getctime, reverse = True)
haqrafiul
-6

Może powinieneś użyć poleceń powłoki. W Unix / Linux, find piped with sort prawdopodobnie będzie w stanie zrobić to, co chcesz.

stephanea
źródło