Làm cách nào để lấy ngày / lần sửa đổi tệp trong Python?


934

Tôi có một tập lệnh cần thực hiện một số nội dung dựa trên ngày tạo và sửa đổi tệp nhưng phải chạy trên Linux & Windows .

Tốt nhất là gì cross-platform cách để có được sự sáng tạo tập tin & sửa đổi date/timestrong Python ?


57
Bạn không thể có được thời gian tạo tập tin theo cách đa nền tảng. Xem docs.python.org/l Library / os.path.html
Glyph

Câu trả lời:


620

Nhận được một số loại ngày sửa đổi theo cách đa nền tảng rất dễ dàng - chỉ cần gọi và bạn sẽ nhận được dấu thời gian Unix khi tệp được sửa đổi lần cuối.os.path.getmtime(path)path

Mặt khác, ngày tạo tệp là phụ thuộc vào nền tảng và phụ thuộc vào nền tảng, khác nhau ngay cả giữa ba hệ điều hành lớn:

Đặt tất cả những thứ này lại với nhau, mã đa nền tảng sẽ trông giống như thế này ...

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

9
Tôi đã làm hết sức mình để cùng nhau giải quyết vấn đề này (và dành vài giờ để nghiên cứu trong quá trình này) và tôi chắc chắn rằng nó ít nhất đúng hơn các câu trả lời trước đây, nhưng đây là một chủ đề rất khó và tôi d đánh giá cao bất kỳ sửa chữa, làm rõ, hoặc đầu vào khác mà mọi người có thể cung cấp. Cụ thể, tôi muốn xây dựng cách truy cập dữ liệu này trên ext4các ổ đĩa trong Linux và tôi muốn tìm hiểu điều gì xảy ra khi Linux đọc các tệp được viết bởi Windows hoặc ngược lại, cho rằng chúng sử dụng st_ctimekhác nhau.
Đánh dấu Amery

25
Thành thật mà nói, thời gian tạo tập tin thường khá vô dụng. Khi bạn mở một tệp hiện có để ghi với chế độ "w", nó không thay thế nó, nó chỉ mở tệp hiện có và cắt bớt nó. Mặc dù nội dung tệp hoàn toàn không liên quan đến bất cứ thứ gì nó tạo ra, bạn vẫn được thông báo rằng tệp đã được "tạo" trước phiên bản hiện tại. Ngược lại, các trình soạn thảo sử dụng thay thế nguyên tử khi lưu (tệp gốc được thay thế bằng tệp tạm thời tiến trình công việc mới) sẽ hiển thị ngày tạo gần đây hơn, ngay cả khi bạn chỉ xóa một ký tự. Sử dụng thời gian sửa đổi, không grub cho thời gian tạo.
ShadowRanger

3
Sau nhiều năm, cuối cùng tôi đã tìm thấy việc sử dụng thời gian tạo tập tin! Tôi đang viết mã để kiểm tra quy ước đặt tên tệp trong một số thư mục nhất định, vì vậy trước hết tôi muốn xem xét các tệp được đặt tên đầu tiên sau khi quy ước được thiết lập. Việc thay thế toàn bộ nội dung (mtime) là không liên quan: nếu nó đã ở đó thì nó đã được tổ chức.
Steve Jessop

1
Xin chào Mark. Tôi đề nghị đơn giản hóa. Trên Linux, việc trở lại stat.st_ctimethích hợp hơn bởi vì, trong nhiều trường hợp, thời gian thay đổi siêu dữ liệu lần cuối có thể là thời gian tạo (ít nhất ctimelà gần với thời gian tạo thực hơn so với mtime). Do đó, bạn chỉ có thể thay thế đoạn trích của mình bằng cách stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Bạn nghĩ sao? Chúc mừng
olibre

4
@olibre "ít nhất là ctime gần với thời gian sáng tạo thực sự hơn mtime" - không, không phải vậy; đây là điều tôi đã thấy nhiều lần nhưng nó hoàn toàn sai. Trừ khi bạn đã tự điều sai lầm với các giá trị trong inode của bạn, ctimenên luôn luôn bằng hoặc sau hơn mtime, bởi vì một mtimesự thay đổi gây ra một ctimesự thay đổi (vì mtimebản thân được coi là "siêu dữ liệu"). Xem stackoverflow.com/a/39521361/1709587 nơi tôi cung cấp một số mã ví dụ để minh họa điều này.
Đánh dấu Amery

676

Bạn có một vài lựa chọn. Đối với một, bạn có thể sử dụng os.path.getmtimevà các os.path.getctimechức năng:

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

Tùy chọn khác của bạn là sử dụng 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))

Lưu ý : ctime()không không đề cập đến thời gian tạo trên hệ thống * nix, mà đúng hơn là lần cuối cùng các dữ liệu inode thay đổi. (cảm ơn kojiro vì đã làm cho sự thật đó rõ ràng hơn trong các bình luận bằng cách cung cấp một liên kết đến một bài đăng blog thú vị)


169
Chỉ trong trường hợp bất cứ ai bỏ lỡ bình luận của @ Glyph cho câu hỏi, ctime không có nghĩa là thời gian tạo trên các hệ thống POSIX . Tôi tự hỏi có bao nhiêu người đã đọc lướt bài đăng này trong ba năm qua và viết mã lỗi.
kojiro

16
Hãy ghi nhớ ví dụ đầu tiên cung cấp cho bạn một chuỗi, không phải là datetime hoặc số.
gak

1
@kojiro các bài viết trên blog bạn đã liên kết để có thể rõ ràng hơn rằng trên Unix một tập tin của ctimeđược cập nhật bất cứ khi nào mtimekhông (vì mtimelà "siêu dữ liệu"), và do đó ctimelà bình thường luôn luôn bằng với hoặc trước các mtime. Đối xử ctimevới thời gian "được tạo ra" do đó không có ý nghĩa gì cả. -1!
Đánh dấu Amery

Tùy chọn đầu tiên của bạn trả về cùng kết quả cho cả việc tạo tệp và sửa đổi lần cuối! Last modified: Fri Jan 31 11:08:13 2020Created: Fri Jan 31 11:08:13 2020trên Linux Ubuntu 16.04!
Färid Alijani

Tôi phát hiện ra rằng time.ctime(os.path.getmtime(file))trả về 2 loại chuỗi, tùy thuộc vào việc tệp đã được sửa đổi bởi hệ thống hay bởi người dùng. Nếu hệ thống đã được sửa đổi, chuỗi sẽ có 2 khoảng trắng giữa tháng và ngày. Tôi không biết tại sao
Matteo Antolini

376

Hàm tốt nhất để sử dụng cho việc này là os.path.getmtime () . Trong nội bộ, điều này chỉ sử dụng os.stat(filename).st_mtime.

Mô-đun datetime là dấu thời gian thao tác tốt nhất, vì vậy bạn có thể lấy ngày sửa đổi dưới dạng một datetimeđối tượng như thế này:

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

Ví dụ sử dụng:

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

1
Câu trả lời này cũng hơi sai một chút. getmtimelà thứ gần nhất có sẵn trên Unix (nơi không thể có ngày tạo), nhưng chắc chắn không phải là chức năng tốt nhất để sử dụng trên Windows, trong đó ctimelà thời gian tạo.
Đánh dấu Amery

3
@MarkAmery - Câu trả lời này được dán nhãn rõ ràng là về thời gian sửa đổi.
ArtOfWarfare

47

os.stat https://docs.python.org/2/l Library / stat.html # mô-đun

chỉnh sửa: Trong mã mới hơn, có lẽ bạn nên sử dụng os.path.getmtime () (cảm ơn Christian Oudard)
nhưng lưu ý rằng nó trả về giá trị dấu phẩy động của time_t với phần giây (nếu hệ điều hành của bạn hỗ trợ nó)


44
os.path.getmtime () được tạo cho việc này và đơn giản hơn.
Christian Oudard

5
Mệnh đề "trong mã mới hơn" ở đây là một chút sai lệch. os.path.getmtime()đã xuất hiện kể từ Python 1.5.2 (xem các tài liệu cũ ), được phát hành trước khi tôi mất hầu hết răng sữa và gần một thập kỷ trước khi bạn viết phiên bản gốc của câu trả lời này.
Mark Amery

39

Có hai phương pháp để lấy thời gian mod, os.path.getmtime () hoặc os.stat (), nhưng ctime không phải là nền tảng chéo đáng tin cậy (xem bên dưới).

os.path.getmtime ()

getmtime ( đường dẫn )
Trả về thời gian sửa đổi cuối cùng của đường dẫn. Giá trị trả về là một số cho số giây kể từ kỷ nguyên (xem mô-đun thời gian). Tăng os.error nếu tệp không tồn tại hoặc không thể truy cập. Mới trong phiên bản 1.5.2. Đã thay đổi trong phiên bản 2.3: Nếu os.stat_float_times () trả về True, kết quả là số dấu phẩy động.

os.stat ()

stat ( path )
Thực hiện lệnh gọi hệ thống stat () trên đường dẫn đã cho. Giá trị trả về là một đối tượng có thuộc tính tương ứng với các thành viên của cấu trúc stat, cụ thể là: st_mode (bit bảo vệ), st_ino (số inode), st_dev (thiết bị), st_nlink (số liên kết cứng), st_uid (ID người dùng của chủ sở hữu ), st_gid (ID nhóm của chủ sở hữu), st_size (kích thước tệp, tính bằng byte), st_atime (thời gian truy cập gần đây nhất), st_mtime (thời gian sửa đổi nội dung gần đây nhất), st_ctime (phụ thuộc nền tảng; thời gian thay đổi siêu dữ liệu gần đây nhất trên Unix hoặc thời điểm tạo trên Windows) :

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

Trong ví dụ trên, bạn sẽ sử dụng statinfo.st_mtime hoặc statinfo.st_ctime để lấy mtime và ctime tương ứng.


13

Trong Python 3.4 trở lên, bạn có thể sử dụng giao diện mô-đun pathlib hướng đối tượng bao gồm các trình bao bọc cho phần lớn mô-đun os. Dưới đây là một ví dụ về việc lấy số liệu thống kê tập tin.

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

Để biết thêm thông tin về những gì os.stat_resultchứa, tham khảo tài liệu . Đối với thời gian sửa đổi bạn muốn 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)

Nếu bạn muốn thời gian tạo trên Windows hoặc thay đổi siêu dữ liệu gần đây nhất trên Unix, bạn sẽ sử dụng fname.stat().st_ctime:

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

Bài viết này có nhiều thông tin và ví dụ hữu ích cho mô-đun pathlib.


11

os.stattrả về một tuple có tên st_mtimest_ctimethuộc tính. Thời gian sửa đổi là st_mtimetrên cả hai nền tảng; Thật không may, trên Windows, ctimecó nghĩa là "thời gian tạo", trong khi trên POSIX, nó có nghĩa là "thay đổi thời gian". Tôi không biết cách nào để có được thời gian tạo trên nền tảng POSIX.


Dưới đây là thông tin thêm về các thẻ được gắn thẻ: stackoverflow.com/questions/2970608/ Khăn Chúng hoạt động như các bộ dữ liệu, nhưng hãy thử dir(..)một cái. Ví dụ:dir(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))

in

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

-1: Giống như các câu trả lời khác, điều này sẽ không cung cấp cho bạn thời gian tạo tệp trên Windows (điều này, một lần nữa, thậm chí không được đề cập trong câu trả lời).
ntninja

@ntninja bạn có chắc về điều đó không? Tôi chỉ sử dụng Windows và điều này hoàn toàn hoạt động. tôi đã viết kịch bản này vào đầu năm 2015. Tôi thấy nó rõ ràng hơn, đi thẳng vào vấn đề, đầy đủ và tự giải thích hơn những người khác ở đây. (điều mà tôi tình cờ quyết định tra cứu ở đây thay vì các kịch bản cũ của tôi chỉ cần có bất kỳ điều gì mới. Không ... đây là cách)
Puddle

Ồ, ý tôi là nói rằng, nhóm, điều này sẽ không cung cấp cho bạn thời gian tạo tập tin, trừ khi bạn đang ở trên Windows. Lấy làm tiếc! Thực tế là câu trả lời này không phải là di động và không đề cập đến thực tế này. (Ví dụ đầu ra trên Linux: pastebin.com/50r5vGBE )
ntninja

@ntninja bạn sẽ đi nói với mọi người sau đó?
Puddle

Đã để lại một số bình luận khác ở đây và tôi sẽ sớm đăng câu trả lời hoạt động trên Linux (gần đây). Nhưng thực sự, điều duy nhất sai trong bài viết của bạn là câu trả lời chỉ dành cho Windows không đề cập đến thực tế này. Trong câu hỏi OP thậm chí còn đặc biệt yêu cầu một giải pháp tương thích với Windows và Linux. Vì vậy, tôi nghĩ sẽ rất hữu ích nếu bạn thêm chi tiết này vào một nơi nào đó trên đỉnh, để mọi người không lầm tưởng rằng ctime là thứ họ đang tìm kiếm khi nhắm mục tiêu vào nhiều nền tảng.
ntninja

2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 

-1: Như đã đề cập ở nơi khác, điều này sẽ không cung cấp cho bạn thời gian tạo tệp, trừ khi bạn ở trên Windows (câu trả lời thậm chí không đề cập đến!).
ntninja

0

Nếu các liên kết tượng trưng sau không quan trọng, bạn cũng có thể sử dụng os.lstatnội dung.

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

Điều này sẽ đưa ra thời gian đọc lần cuối (ít nhất là trên Unix), đây chắc chắn không phải là điều được yêu cầu.
Đánh dấu Amery

0

Có thể đáng để xem crtimethư viện thực hiện truy cập đa nền tảng vào thời gian tạo tệp.

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

1
Tôi thực sự khuyên bạn nên chống lại điều này: Nó sử dụng debugfstrên Linux, theo định nghĩa không ổn định, yêu cầu quyền truy cập root cấp cao nhất cho mọi thứ và hầu như mọi khía cạnh đều có xu hướng là một trong những điều mẹ bạn luôn cảnh báo bạn. (Nhưng vâng, nó có thể hoạt động nếu bạn thực sự tuyệt vọng và tình
cờ

@ntninja Có lẽ tôi sẽ không bao giờ sử dụng trong sản xuất, nhưng nó có thể hữu ích cho "kịch bản tại nhà".
Delgan

-2

os.statkhông bao gồm thời gian tạo. Không có định nghĩa về st_anything cho phần tử os.stat()chứa thời gian.

Vì vậy, hãy thử điều này:

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

So sánh với ngày tạo của bạn trên tệp trong ls-nhớ

Chắc họ giống nhau.


6
Sai lầm! os.stat ('feedparser.py') [8] đề cập đến st_mtime, không phải thời gian tạo. Vui lòng tham khảo tài liệu hướng dẫn: docs.python.org/library/os.html#os.stat
millerdev

4
Vui lòng sử dụng .st_ctime thay vì số xấu [8].
guettli

-3

Tôi đã có thể có được thời gian tạo trên posix bằng cách chạy lệnh stat của hệ thống và phân tích cú pháp đầu ra.

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

Chạy stat bên ngoài python từ Terminal (OS X) đã trả về:

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

... Trong đó datetime thứ tư là việc tạo tệp (thay vì thời gian thay đổi thời gian như các bình luận khác đã lưu ý).


13
-1: Phân tích cú pháp đầu ra có nghĩa là cho con người từ lệnh shell là một ý tưởng rất tồi. Và lệnh này thậm chí không tương thích chéo.
MestreLion
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.