Comment obtenir la date / heure de création et de modification d'un fichier en Python?

934

J'ai un script qui doit faire certaines choses en fonction des dates de création et de modification de fichiers mais doit fonctionner sous Linux et Windows .

Quelle est la meilleure façon multiplateforme d'obtenir la création et la modification de fichiers date/timesen Python ?

Mark Biek
la source
57
Vous ne pouvez pas obtenir le temps de création de fichier de manière multiplateforme. Voir docs.python.org/library/os.path.html#os.path.getctime
Glyphe

Réponses:

621

Obtenir une sorte de date de modification de manière multiplateforme est facile - il suffit d'appeler et vous obtiendrez l'horodatage Unix de la dernière modification du fichier .os.path.getmtime(path)path

D'un autre côté, l' obtention des dates de création de fichiers dépend de la complexité et de la plate-forme, même entre les trois gros systèmes d'exploitation:

En mettant tout cela ensemble, le code multiplateforme devrait ressembler à ceci ...

import os
import platform

def creation_date(path_to_file):
    """
    Try to get the date that a file was created, falling back to when it was
    last modified if that isn't possible.
    See http://stackoverflow.com/a/39501288/1709587 for explanation.
    """
    if platform.system() == 'Windows':
        return os.path.getctime(path_to_file)
    else:
        stat = os.stat(path_to_file)
        try:
            return stat.st_birthtime
        except AttributeError:
            # We're probably on Linux. No easy way to get creation dates here,
            # so we'll settle for when its content was last modified.
            return stat.st_mtime
Mark Amery
la source
9
J'ai fait de mon mieux pour mettre cela ensemble (et j'ai passé quelques heures à faire des recherches dans le processus), et je suis sûr que c'est au moins plus correct que les réponses qui étaient ici précédemment, mais c'est un sujet vraiment difficile et je '' d apprécier les corrections, clarifications ou autres contributions que les gens peuvent offrir. En particulier, je voudrais construire un moyen d'accéder à ces données sur des ext4disques sous Linux, et j'aimerais savoir ce qui se passe lorsque Linux lit des fichiers écrits par Windows, ou vice versa, étant donné qu'ils utilisent st_ctimedifféremment.
Mark Amery du
25
Franchement, le temps de création de fichier est généralement assez inutile. Lorsque vous ouvrez un fichier existant pour l'écriture avec le mode "w", il ne le remplace pas, il ouvre simplement le fichier existant et le tronque. Même si le contenu du fichier n'a aucun rapport avec ce qu'il avait lors de sa création, on vous dirait tout de même que le fichier a été "créé" bien avant la version actuelle. Inversement, les éditeurs qui utilisent le remplacement atomique lors de l'enregistrement (le fichier d'origine est remplacé par un nouveau fichier temporaire en cours de travail) afficheraient une date de création plus récente, même si vous venez de supprimer un caractère. Utilisez l'heure de modification, ne cherchez pas l'heure de création.
ShadowRanger du
3
Après de nombreuses années, j'ai enfin trouvé une utilisation pour le temps de création de fichiers! J'écris du code pour vérifier une convention de dénomination de fichier dans certains répertoires, donc tout d'abord je veux considérer les fichiers qui ont été nommés pour la première fois après l'instauration de la convention. Le remplacement de l'intégralité du contenu (mtime) n'est pas pertinent: s'il était déjà là, il est protégé par des droits acquis.
Steve Jessop
1
Salut Mark. Je propose une simplification. Sous Linux, le retour stat.st_ctimeest plus pertinent car, dans de nombreux cas, l'heure du dernier changement de métadonnées peut être l'heure de création (au moins ctimeplus proche de l' heure de création réelle que mtime). Par conséquent, vous pouvez simplement remplacer votre extrait par stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Qu'est-ce que tu penses? Vive
olibre
4
@olibre "au moins ctime est plus proche du temps de création réel que mtime" - non, ce n'est pas le cas; c'est quelque chose que j'ai vu plusieurs fois, mais c'est totalement faux. Sauf si vous avez manipulé manuellement les valeurs de votre inode, elles ctimedoivent toujours être égales ou supérieures à mtime, car une mtimemodification entraîne une ctimemodification (car mtimeelle-même est considérée comme des "métadonnées"). Voir stackoverflow.com/a/39521489/1709587 où je fournis un exemple de code pour illustrer cela.
Mark Amery
676

Vous avez deux choix. D'une part, vous pouvez utiliser les fonctions os.path.getmtimeet os.path.getctime:

import os.path, time
print("last modified: %s" % time.ctime(os.path.getmtime(file)))
print("created: %s" % time.ctime(os.path.getctime(file)))

Votre autre option consiste à utiliser os.stat:

import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print("last modified: %s" % time.ctime(mtime))

Remarque : ctime()ne fait pas référence à l'heure de création sur les systèmes * nix, mais plutôt à la dernière modification des données d'inode. (merci à kojiro d'avoir clarifié ce fait dans les commentaires en fournissant un lien vers un article de blog intéressant)

Bryan Oakley
la source
169
Juste au cas où quelqu'un manquerait le commentaire de @ Glyph à la question, ctime ne signifie pas le temps de création sur les systèmes POSIX . Je me demande combien de personnes ont survolé ce post au cours des trois dernières années et ont continué à écrire du code buggy.
kojiro
16
Gardez à l'esprit que le premier exemple vous donne une chaîne, pas un datetime ou un nombre.
gak
1
@kojiro le blog que vous avez lié à pourrait être plus explicite que sur Unix de fichier ctimeest mis à jour chaque fois que le mtimefait (depuis mtimeest « métadonnées »), et donc le ctimeest normalement toujours égal à ou avant la mtime. Traiter ctimecomme du temps "créé" n'a donc aucun sens. -1!
Mark Amery
Votre première option renvoie les mêmes résultats pour la création de fichiers et la dernière modification! Last modified: Fri Jan 31 11:08:13 2020et Created: Fri Jan 31 11:08:13 2020sur Linux Ubuntu 16.04!
Färid Alijani
Je découvre que time.ctime(os.path.getmtime(file))renvoie 2 types de chaînes, selon que le fichier a été modifié par le système ou par l'utilisateur. Si elle a été modifiée par le système, la chaîne aura 2 espaces entre le mois et le jour. Je ne sais pas pourquoi
Matteo Antolini
376

La meilleure fonction à utiliser pour cela est os.path.getmtime () . En interne, cela utilise simplement os.stat(filename).st_mtime.

Le module datetime est le meilleur des horodatages de manipulation, vous pouvez donc obtenir la date de modification sous la forme d'un datetimeobjet comme celui-ci:

import os
import datetime
def modification_date(filename):
    t = os.path.getmtime(filename)
    return datetime.datetime.fromtimestamp(t)

Exemple d'utilisation:

>>> d = modification_date('/var/log/syslog')
>>> print d
2009-10-06 10:50:01
>>> print repr(d)
datetime.datetime(2009, 10, 6, 10, 50, 1)
Christian Oudard
la source
1
Cette réponse est également un peu fausse. getmtimeest la chose la plus proche disponible sur Unix (où obtenir des dates de création n'est pas possible), mais ce n'est certainement pas la meilleure fonction à utiliser sur Windows, où le ctimeest un temps de création.
Mark Amery du
3
@MarkAmery - Cette réponse est clairement étiquetée comme étant simplement sur le temps de modification.
ArtOfWarfare
47

os.stat https://docs.python.org/2/library/stat.html#module-stat

edit: Dans un code plus récent, vous devriez probablement utiliser os.path.getmtime () (merci Christian Oudard)
mais notez qu'il renvoie une valeur à virgule flottante de time_t avec des secondes de fraction (si votre système d'exploitation le prend en charge)

Martin Beckett
la source
44
os.path.getmtime () est fait pour cela, et plus simple.
Christian Oudard
5
La clause "dans un code plus récent" ici est un peu trompeuse. os.path.getmtime()existe depuis Python 1.5.2 (voir les anciens documents ), publié avant que j'aie perdu la plupart de mes dents de lait et près d'une décennie avant que vous n'écriviez la version originale de cette réponse.
Mark Amery
39

Il existe deux méthodes pour obtenir l'heure du mod, os.path.getmtime () ou os.stat (), mais le ctime n'est pas fiable multiplateforme (voir ci-dessous).

os.path.getmtime ()

getmtime ( chemin )
Renvoie l'heure de la dernière modification du chemin. La valeur de retour est un nombre donnant le nombre de secondes écoulées depuis l'époque (voir le module de temps). Relancez os.error si le fichier n'existe pas ou est inaccessible. Nouveau dans la version 1.5.2. Modifié dans la version 2.3: si os.stat_float_times () renvoie True, le résultat est un nombre à virgule flottante.

os.stat ()

stat ( path )
Effectue un appel système stat () sur le chemin donné. La valeur de retour est un objet dont les attributs correspondent aux membres de la structure stat, à savoir: st_mode (bits de protection), st_ino (numéro d'inode), st_dev (périphérique), st_nlink (nombre de liens durs), st_uid (ID utilisateur du propriétaire ), st_gid (ID de groupe du propriétaire), st_size (taille du fichier, en octets), st_atime (heure de l'accès le plus récent), st_mtime (heure de la dernière modification de contenu), st_ctime (en fonction de la plateforme; heure de la dernière modification des métadonnées) sous Unix, ou l'heure de création sous Windows) :

>>> import os
>>> statinfo = os.stat('somefile.txt')
>>> statinfo
(33188, 422511L, 769L, 1, 1032, 100, 926L, 1105022698,1105022732, 1105022732)
>>> statinfo.st_size
926L
>>> 

Dans l'exemple ci-dessus, vous utiliseriez statinfo.st_mtime ou statinfo.st_ctime pour obtenir respectivement mtime et ctime.

Geai
la source
13

Dans Python 3.4 et supérieur, vous pouvez utiliser l' interface du module pathlib orienté objet qui inclut des wrappers pour une grande partie du module os. Voici un exemple d'obtention des statistiques du fichier.

>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}'  # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)

Pour plus d'informations sur ce qui os.stat_resultcontient, reportez-vous à la documentation . Pour l'heure de modification que vous souhaitez fname.stat().st_mtime:

>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)

Si vous voulez l'heure de création sur Windows, ou la modification de métadonnées la plus récente sur Unix, vous utiliseriez fname.stat().st_ctime:

>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)

Cet article contient des informations et des exemples plus utiles pour le module pathlib.

Steven C. Howell
la source
11

os.statrenvoie un tuple nommé avec des attributs st_mtimeet st_ctime. L'heure de modification est st_mtimesur les deux plates-formes; malheureusement, sous Windows, ctimesignifie «heure de création», tandis que sur POSIX, cela signifie «changer l'heure». Je ne connais aucun moyen d'obtenir l'heure de création sur les plates-formes POSIX.

mithrandi
la source
Voici plus d'informations sur les tuples marqués: stackoverflow.com/questions/2970608/… Ils fonctionnent comme des tuples, mais essayez- dir(..)en un. Par exempledir(os.stat(os.listdir('.')[0]))
Evgeni Sergeev
9
import os, time, datetime

file = "somefile.txt"
print(file)

print("Modified")
print(os.stat(file)[-2])
print(os.stat(file).st_mtime)
print(os.path.getmtime(file))

print()

print("Created")
print(os.stat(file)[-1])
print(os.stat(file).st_ctime)
print(os.path.getctime(file))

print()

modified = os.path.getmtime(file)
print("Date modified: "+time.ctime(modified))
print("Date modified:",datetime.datetime.fromtimestamp(modified))
year,month,day,hour,minute,second=time.localtime(modified)[:-3]
print("Date modified: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))

print()

created = os.path.getctime(file)
print("Date created: "+time.ctime(created))
print("Date created:",datetime.datetime.fromtimestamp(created))
year,month,day,hour,minute,second=time.localtime(created)[:-3]
print("Date created: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))

impressions

somefile.txt
Modified
1429613446
1429613446.0
1429613446.0

Created
1517491049
1517491049.28306
1517491049.28306

Date modified: Tue Apr 21 11:50:46 2015
Date modified: 2015-04-21 11:50:46
Date modified: 21/04/2015 11:50:46

Date created: Thu Feb  1 13:17:29 2018
Date created: 2018-02-01 13:17:29.283060
Date created: 01/02/2018 13:17:29
Flaque
la source
-1: Identique aux autres réponses, cela ne vous donnera pas l'heure de création du fichier sous Windows (qui, encore une fois, n'est même pas mentionnée dans la réponse).
ntninja
@ntninja en êtes-vous sûr? j'utilise uniquement Windows et cela fonctionne absolument. J'ai écrit ce script au début de 2015. Je trouve qu'il était plus clair, direct, complet et explicite que d'autres ici. (que je est arrivé de décider de regarder ici au lieu de mes anciens scripts juste au cas il y avait quelque chose de nouveau ... ce Nope est le chemin.)
Puddle
Oh, je voulais dire «… cela ne vous donnera pas le temps de création du fichier, sauf si vous êtes sous Windows». Désolé! Le fait demeure que cette réponse n'est pas portable et ne mentionne pas ce fait. (Exemple de sortie sur Linux: pastebin.com/50r5vGBE )
ntninja
@ntninja tu vas aller le dire à tout le monde alors?
Flaque d'
J'ai déjà laissé d'autres commentaires ici et je posterai bientôt une réponse qui fonctionne sur Linux (récent). Mais vraiment, la seule chose qui cloche dans votre message est que c'est une réponse Windows uniquement qui ne mentionne pas ce fait. Dans la question OP a même spécifiquement demandé une solution compatible Windows et Linux. En tant que tel, je pense qu'il serait très utile que vous ajoutiez ce «détail» quelque part en haut, afin que les gens ne se trompent pas en pensant que ctime est ce qu'ils recherchent lorsqu'ils ciblent plusieurs plates-formes.
ntninja
2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 
démonté
la source
-1: Comme mentionné ailleurs, cela ne vous donnera pas le temps de création du fichier, sauf si vous êtes sous Windows (ce que la réponse ne mentionne même pas!).
ntninja
0

Si les liens symboliques suivants ne sont pas importants, vous pouvez également utiliser la fonction os.lstatintégrée.

>>> os.lstat("2048.py")
posix.stat_result(st_mode=33188, st_ino=4172202, st_dev=16777218L, st_nlink=1, st_uid=501, st_gid=20, st_size=2078, st_atime=1423378041, st_mtime=1423377552, st_ctime=1423377553)
>>> os.lstat("2048.py").st_atime
1423378041.0
Low Kian Seong
la source
Cela donnera l'heure de la dernière lecture (au moins sur Unix), ce qui n'est certainement pas ce qui a été demandé.
Mark Amery
0

Il peut être utile de jeter un œil à la crtimebibliothèque qui implémente l'accès multiplateforme au moment de la création du fichier.

from crtime import get_crtimes_in_dir

for fname, date in get_crtimes_in_dir(".", raise_on_error=True, as_epoch=False):
    print(fname, date)
    # file_a.py Mon Mar 18 20:51:18 CET 2019
Delgan
la source
1
Je déconseille fortement cela: il utilise debugfssous Linux qui est par définition instable, nécessite un accès root de haut niveau pour tout et à peu près tous les aspects ont tendance à être l'une des choses dont votre mère vous a toujours prévenu. (Mais oui, cela fonctionne probablement si vous êtes vraiment désespéré et que vous êtes le vrai superutilisateur sur un système sans démarrage sécurisé…)
ntninja
@ntninja Je ne l'emploierais probablement jamais non plus en production, mais cela peut être utile pour le "home scripting".
Delgan
-2

os.statne comprend pas le temps de création. Il n'y a tout simplement pas de définition de st_anything pour l'élément os.stat()qui contient le temps.

Essayez donc ceci:

os.stat('feedparser.py')[8]

Comparez cela avec votre date de création sur le fichier dans ls -lah

Ils devraient être les mêmes.

Barre
la source
6
Faux! os.stat ('feedparser.py') [8] fait référence à st_mtime, pas à l'heure de création. Veuillez vous référer à la documentation: docs.python.org/library/os.html#os.stat
millerdev
4
Veuillez utiliser .st_ctime au lieu de chiffres laids [8].
guettli
-3

J'ai pu obtenir du temps de création sur posix en exécutant la commande stat du système et en analysant la sortie.

commands.getoutput('stat FILENAME').split('\"')[7]

L'exécution de stat en dehors de python à partir du terminal (OS X) a renvoyé:

805306374 3382786932 -rwx------ 1 km staff 0 1098083 "Aug 29 12:02:05 2013" "Aug 29 12:02:05 2013" "Aug 29 12:02:20 2013" "Aug 27 12:35:28 2013" 61440 2150 0 testfile.txt

... où le quatrième datetime est la création du fichier (plutôt que le temps de changement ctime comme d'autres commentaires l'ont noté).

kmarchand
la source
13
-1: L'analyse d'une sortie destinée aux humains à partir d'une commande shell est une très mauvaise idée. Et cette commande n'est même pas compatible croisée.
MestreLion