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/times
trong Python ?
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/times
trong Python ?
Câu trả lời:
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:
ctime
(được ghi lại tại https://msdn.microsoft.com/en-us/l Library / 14h5k7ff.aspx ) lưu trữ ngày tạo của nó. Bạn có thể truy cập cái này trong Python thông qua os.path.getctime()
hoặc .st_ctime
thuộc tính kết quả của một cuộc gọi đến os.stat()
. Điều này sẽ không hoạt động trên Unix, nơi đây ctime
là lần cuối cùng các thuộc tính hoặc nội dung của tệp được thay đổi ..st_birthtime
thuộc tính kết quả của một cuộc gọi đến os.stat()
.Trên Linux , điều này hiện không thể, ít nhất là không viết phần mở rộng C cho Python. Mặc dù một số hệ thống tệp thường được sử dụng với Linux thực hiện lưu trữ ngày tạo (ví dụ: ext4
lưu trữ chúng st_crtime
), nhân Linux không cung cấp cách nào để truy cập chúng ; đặc biệt, các cấu trúc mà nó trả về từ stat()
các cuộc gọi trong C, kể từ phiên bản kernel mới nhất, không chứa bất kỳ trường ngày tạo nào . Bạn cũng có thể thấy rằng mã định danh st_crtime
hiện không có tính năng ở bất kỳ đâu trong nguồn Python . Ít nhất là nếu bạn bật ext4
, dữ liệu được gắn vào các nút trong hệ thống tệp, nhưng không có cách nào thuận tiện để truy cập nó.
Điều tốt nhất tiếp theo trên Linux là truy cập vào tệp mtime
, thông qua os.path.getmtime()
hoặc .st_mtime
thuộc tính của os.stat()
kết quả. Điều này sẽ cung cấp cho bạn lần cuối cùng nội dung của tệp được sửa đổi, có thể phù hợp với một số trường hợp sử dụng.
Đặ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
ext4
cá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_ctime
khác nhau.
"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.
stat.st_ctime
thí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 ctime
là 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
ctime
nên luôn luôn bằng hoặc sau hơn mtime
, bởi vì một mtime
sự thay đổi gây ra một ctime
sự thay đổi (vì mtime
bả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.
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.getmtime
và các os.path.getctime
chứ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ị)
ctime
được cập nhật bất cứ khi nào mtime
không (vì mtime
là "siêu dữ liệu"), và do đó ctime
là bình thường luôn luôn bằng với hoặc trước các mtime
. Đối xử ctime
với thời gian "được tạo ra" do đó không có ý nghĩa gì cả. -1!
Last modified: Fri Jan 31 11:08:13 2020
và Created: Fri Jan 31 11:08:13 2020
trên Linux Ubuntu 16.04!
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
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)
getmtime
là 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 đó ctime
là thời gian tạo.
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ó)
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.
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).
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.
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.
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_result
chứ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.
os.stat
trả về một tuple có tên st_mtime
và st_ctime
thuộc tính. Thời gian sửa đổi là st_mtime
trên cả hai nền tảng; Thật không may, trên Windows, ctime
có 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.
dir(..)
một cái. Ví dụ:dir(os.stat(os.listdir('.')[0]))
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
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>>
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.lstat
nộ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
Có thể đáng để xem crtime
thư 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
debugfs
trê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
os.stat
khô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.
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 ý).