Bagaimana cara mendapatkan tanggal / kali pembuatan & modifikasi file dengan Python?

934

Saya memiliki skrip yang perlu melakukan beberapa hal berdasarkan tanggal pembuatan & modifikasi file tetapi harus dijalankan di Linux & Windows .

Apa cara lintas platform terbaik untuk mendapatkan kreasi & modifikasi file date/timesdengan Python ?

Mark Biek
sumber
57
Anda tidak bisa mendapatkan waktu pembuatan file dengan cara lintas platform. Lihat docs.python.org/library/os.path.html#os.path.getctime
Glyph

Jawaban:

621

Mendapatkan semacam tanggal modifikasi dengan cara lintas-platform itu mudah - panggil saja dan Anda akan mendapatkan cap waktu Unix kapan file terakhir diubah.os.path.getmtime(path)path

Sebaliknya, mendapatkan tanggal pembuatan file sangat tergantung dan tergantung platform, bahkan berbeda antara tiga OS besar:

Menyatukan semua ini, kode lintas-platform akan terlihat seperti ini ...

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
sumber
9
Saya sudah melakukan yang terbaik untuk menyatukan ini (dan menghabiskan beberapa jam meneliti dalam proses), dan saya yakin itu setidaknya lebih benar daripada jawaban yang ada di sini sebelumnya, tapi ini adalah topik yang sangat sulit dan saya ' d menghargai setiap koreksi, klarifikasi, atau masukan lain yang dapat ditawarkan orang. Secara khusus, saya ingin membangun cara mengakses data ini pada ext4drive di Linux, dan saya ingin mempelajari apa yang terjadi ketika Linux membaca file yang ditulis oleh Windows, atau vica versa, mengingat bahwa mereka menggunakan secara st_ctimeberbeda.
Mark Amery
25
Terus terang, waktu pembuatan file biasanya tidak berguna. Ketika Anda membuka file yang ada untuk mode tulis "w", itu tidak akan menggantikannya, itu hanya membuka file yang ada dan memotongnya. Meskipun konten file sama sekali tidak terkait dengan apa pun yang ada pada pembuatan, Anda masih akan diberitahu bahwa file itu "dibuat" jauh sebelum versi saat ini. Sebaliknya, editor yang menggunakan penggantian atom pada save (file asli digantikan oleh file temp yang sedang dalam proses) akan menunjukkan tanggal pembuatan yang lebih baru, bahkan jika Anda baru saja menghapus satu karakter. Gunakan waktu modifikasi, jangan grub untuk waktu pembuatan.
ShadowRanger
3
Setelah bertahun-tahun, saya akhirnya menemukan kegunaan untuk waktu pembuatan file! Saya menulis kode untuk memeriksa konvensi penamaan file di direktori tertentu, jadi pertama-tama saya ingin mempertimbangkan file yang pertama kali dinamai setelah konvensi dilembagakan. Mengganti seluruh konten (mtime) tidak relevan: jika sudah ada di sana maka itu sudah menjadi milik kakek.
Steve Jessop
1
Hai Mark. Saya mengusulkan penyederhanaan. Di Linux, pengembalian stat.st_ctimelebih relevan karena, dalam banyak kasus, waktu perubahan metadata terakhir bisa menjadi waktu pembuatan (setidaknya ctimelebih dekat dengan waktu pembuatan sebenarnya daripada mtime). Karenanya, Anda cukup mengganti snippet dengan stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Bagaimana menurut anda? Cheers
olibre
4
@ Colibre "setidaknya ctime lebih dekat ke waktu pembuatan nyata daripada mtime" - tidak, bukan; ini adalah sesuatu yang pernah saya lihat beberapa kali tetapi ini benar-benar salah. Kecuali Anda sudah secara manual mengacaukan dengan nilai-nilai dalam inode Anda, ctimeharus selalu sama dengan atau lambat dibandingkan mtime, karena sebuah mtimeperubahan menyebabkan suatu ctimeperubahan (karena mtimeitu sendiri dianggap "metadata"). Lihat stackoverflow.com/a/39521489/1709587 di mana saya memberikan beberapa contoh kode untuk menggambarkan hal ini.
Mark Amery
676

Anda punya beberapa pilihan. Untuk satu, Anda dapat menggunakan os.path.getmtimedan os.path.getctimefungsinya:

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

Pilihan Anda yang lain adalah menggunakan 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))

Catatan : ctime()tidak tidak mengacu pada waktu penciptaan pada sistem nix *, melainkan terakhir kali data inode berubah. (terima kasih kepada kojiro untuk membuat fakta itu lebih jelas di komentar dengan memberikan tautan ke posting blog yang menarik)

Bryan Oakley
sumber
169
Kalau-kalau ada orang yang melewatkan komentar @ Glyph untuk pertanyaan tersebut, ctime tidak berarti waktu pembuatan pada sistem POSIX . Saya bertanya-tanya berapa banyak orang yang membaca sekilas posting ini selama tiga tahun terakhir dan terus menulis kode buggy.
kojiro
16
Ingat, contoh pertama memberi Anda string, bukan datetime atau angka.
gak
1
@kojiro posting blog Anda terkait dengan bisa lebih eksplisit bahwa pada Unix file ini ctimeakan diperbarui setiap kali mtimetidak (karena mtimemerupakan "metadata"), sehingga ctimebiasanya selalu sama untuk atau menjelang tersebut mtime. Memperlakukan ctimewaktu "diciptakan" tidak masuk akal sama sekali. -1!
Mark Amery
Opsi pertama Anda mengembalikan hasil yang sama untuk pembuatan file dan modifikasi terakhir! Last modified: Fri Jan 31 11:08:13 2020dan Created: Fri Jan 31 11:08:13 2020di Linux Ubuntu 16.04!
Färid Alijani
Saya menemukan bahwa time.ctime(os.path.getmtime(file))mengembalikan 2 jenis string, tergantung apakah file telah dimodifikasi oleh sistem atau oleh pengguna. Jika telah dimodifikasi oleh sistem, string akan memiliki 2 spasi antara bulan dan hari. Saya tidak tahu mengapa
Matteo Antolini
376

Fungsi terbaik yang digunakan untuk ini adalah os.path.getmtime () . Secara internal, ini hanya menggunakan os.stat(filename).st_mtime.

Modul datetime adalah cap waktu manipulasi terbaik, sehingga Anda bisa mendapatkan tanggal modifikasi sebagai datetimeobjek seperti ini:

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

Contoh penggunaan:

>>> 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
sumber
1
Jawaban ini juga sedikit salah. getmtimeadalah hal terdekat yang tersedia di Unix (di mana mendapatkan tanggal pembuatan tidak mungkin), tetapi jelas bukan fungsi terbaik untuk digunakan di Windows, di mana ctimewaktu pembuatannya adalah.
Mark Amery
3
@MarkAmery - Jawaban ini jelas dilabeli hanya tentang waktu modifikasi.
ArtOfWarfare
47

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

sunting: Dalam kode yang lebih baru Anda mungkin harus menggunakan os.path.getmtime () (terima kasih Christian Oudard)
tetapi perhatikan bahwa ia mengembalikan nilai floating point time_t dengan fraksi detik (jika OS Anda mendukungnya)

Martin Beckett
sumber
44
os.path.getmtime () dibuat untuk ini, dan lebih sederhana.
Christian Oudard
5
Klausa "dalam kode yang lebih baru" di sini agak menyesatkan. os.path.getmtime()telah ada sejak Python 1.5.2 (lihat dokumen lama ), dirilis sebelum saya kehilangan sebagian besar gigi bayi saya dan hampir satu dekade sebelum Anda menulis versi asli dari jawaban ini.
Mark Amery
39

Ada dua metode untuk mendapatkan waktu mod, os.path.getmtime () atau os.stat (), tetapi ctime tidak dapat diandalkan lintas-platform (lihat di bawah).

os.path.getmtime ()

getmtime ( path )
Mengembalikan waktu modifikasi path terakhir. Nilai kembali adalah angka yang memberikan jumlah detik sejak zaman (lihat modul waktu). Naikkan os.error jika file tidak ada atau tidak dapat diakses. Baru dalam versi 1.5.2. Berubah dalam versi 2.3: Jika os.stat_float_times () mengembalikan True, hasilnya adalah angka floating point.

os.stat ()

stat ( jalur )
Lakukan panggilan sistem stat () di jalur yang diberikan. Nilai kembali adalah objek yang atributnya sesuai dengan anggota struktur stat, yaitu: st_mode (bit perlindungan), st_ino (nomor inode), st_dev (perangkat), st_nlink (jumlah tautan keras), st_uid (ID pengguna pemilik) ), st_gid (ID grup pemilik), st_size (ukuran file, dalam bytes), st_atime (waktu akses terkini), st_mtime (waktu modifikasi konten terkini), st_ctime (ketergantungan platform; waktu perubahan metadata terbaru) di Unix, atau saat pembuatan di Windows) :

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

Dalam contoh di atas Anda akan menggunakan statinfo.st_mtime atau statinfo.st_ctime untuk mendapatkan waktu mtime dan ctime.

Jay
sumber
13

Dalam Python 3.4 dan di atas, Anda dapat menggunakan antarmuka modul pathlib berorientasi objek yang mencakup pembungkus untuk sebagian besar modul os. Berikut adalah contoh untuk mendapatkan statistik file.

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

Untuk informasi lebih lanjut tentang apa yang os.stat_resultmengandung, rujuk ke dokumentasi . Untuk waktu modifikasi yang Anda inginkan 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)

Jika Anda ingin waktu pembuatan di Windows, atau perubahan metadata terbaru di Unix, Anda akan menggunakan fname.stat().st_ctime:

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

Artikel ini memiliki informasi dan contoh yang lebih bermanfaat untuk modul pathlib.

Steven C. Howell
sumber
11

os.statmengembalikan tuple dengan nama st_mtimedan st_ctimeatribut. Waktu modifikasi ada st_mtimedi kedua platform; sayangnya, pada Windows, ctimeberarti "waktu pembuatan", sedangkan pada POSIX itu berarti "ubah waktu". Saya tidak mengetahui cara apa pun untuk mendapatkan waktu pembuatan pada platform POSIX.

mithrandi
sumber
Berikut ini lebih lanjut tentang tagged-tuple: stackoverflow.com/questions/2970608/... Mereka bekerja seperti tuple, tetapi coba dir(..)salah satunya. Misalnyadir(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))

cetakan

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
Genangan air
sumber
-1: Sama seperti jawaban lain, ini tidak akan memberi Anda waktu pembuatan file di Windows (yang, sekali lagi, bahkan tidak disebutkan dalam jawaban).
ntninja
@ntninja, apakah Anda yakin tentang itu? Saya hanya menggunakan Windows dan ini benar-benar berfungsi. saya menulis skrip ini pada awal 2015. saya merasa lebih jelas, langsung ke intinya, lengkap dan jelas dari yang lain di sini. (yang kebetulan saya putuskan untuk mencari di sini alih-alih skrip lama saya hanya memetikan ada sesuatu yang baru. tidak ... ini jalannya)
Puddle
Oh, saya bermaksud mengatakan "... ini tidak akan memberi Anda waktu pembuatan file, kecuali jika Anda menggunakan Windows". Maaf! Fakta tetap bahwa jawaban ini tidak portabel dan tidak menyebutkan fakta ini. (Contoh output di Linux: pastebin.com/50r5vGBE )
ntninja
@ Bukankah Ninja Anda akan pergi memberitahu orang lain kalau begitu?
Genangan
Sudah meninggalkan beberapa komentar lain di sini dan saya akan memposting jawaban yang berfungsi pada (baru) Linux juga segera. Tapi sungguh, satu-satunya hal yang salah dalam posting Anda adalah jawaban Windows saja yang tidak menyebutkan fakta ini. Dalam pertanyaan OP bahkan secara khusus meminta solusi yang kompatibel dengan Windows dan Linux. Karena itu saya pikir akan sangat membantu jika Anda menambahkan "detail" ini di suatu tempat di bagian atas, sehingga orang tidak salah dalam berpikir bahwa waktu adalah apa yang mereka cari ketika menargetkan berbagai platform.
ntninja
2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 
lepas
sumber
-1: Seperti yang disebutkan di tempat lain, ini tidak akan memberi Anda waktu pembuatan file, kecuali jika Anda menggunakan Windows (yang jawabannya bahkan tidak disebutkan!).
ntninja
0

Jika tautan simbolis berikut tidak penting, Anda juga dapat menggunakan os.lstatbuiltin.

>>> 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
sumber
Ini akan memberikan waktu membaca terakhir (setidaknya di Unix), yang jelas bukan yang diminta.
Mark Amery
0

Mungkin patut melihat crtimeperpustakaan yang mengimplementasikan akses lintas platform ke waktu pembuatan file.

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
sumber
1
Saya sangat menyarankan ini: Ini digunakan debugfsdi Linux yang menurut definisi tidak stabil, membutuhkan akses root tingkat atas untuk semuanya dan hampir setiap aspek cenderung menjadi salah satu hal yang selalu diperingatkan ibu Anda. (Tapi ya, itu mungkin bekerja jika Anda benar-benar putus asa dan kebetulan menjadi pengguna
super
@ntninja Saya mungkin tidak akan pernah menggunakan dalam produksi juga, tetapi mungkin berguna untuk "home scripting".
Delgan
-2

os.stattidak termasuk waktu pembuatan. Tidak ada definisi st_anything untuk elemen os.stat()yang mengandung waktu.

Jadi coba ini:

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

Bandingkan dengan tanggal pembuatan Anda pada file di ls -lah

Mereka harus sama.

tongkat
sumber
6
Salah! os.stat ('feedparser.py') [8] mengacu pada st_mtime, bukan waktu pembuatan. Silakan merujuk ke dokumentasi: docs.python.org/library/os.html#os.stat
millerdev
4
Silakan gunakan .st_ctime alih-alih angka jelek [8].
guettli
-3

Saya bisa mendapatkan waktu pembuatan pada posix dengan menjalankan perintah stat sistem dan mem-parsing output.

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

Menjalankan stat di luar python dari Terminal (OS X) kembali:

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

... di mana datetime keempat adalah pembuatan file (bukan waktu perubahan waktu seperti komentar lain dicatat).

kmarchand
sumber
13
-1: Mengurai output yang dimaksudkan untuk manusia dari perintah shell adalah ide yang sangat buruk. Dan perintah ini bahkan tidak kompatibel lintas.
MestreLion