【问题标题】:Get file creation time with Python on Mac在 Mac 上使用 Python 获取文件创建时间
【发布时间】:2019-03-19 04:16:40
【问题描述】:

Mac 上的 Python os.path.getctime(以及一般的 Unix 下)没有给出文件创建的日期,而是“最后一次更改的时间”(至少根据文档)。另一方面,在 Finder 中,我可以看到真实的文件创建时间,因此这些信息由 HFS+ 保存。

您对如何在 Mac 上通过 Python 程序获取文件创建时间有什么建议吗?

【问题讨论】:

  • @S.Lott:不是真的,因为在 Mac 上获取文件创建时间本质上是非跨平台的。
  • @Miles:也许是真的,但那里的答案完全适用于这个问题。
  • @S.Lott:这不是重复的,相信我那里的答案根本不适用于 Mac(除非你接受答案是有没有办法在 Mac 上获得 Miles 证明是错误的创建时间)。在 Mac 上,os.path.getctime 和 os.stat 都给出了最后的 change 时间,而不是创建时间。所以说 os.stat 是获取创建时间的跨平台方法的人都是错误的。

标签: python macos


【解决方案1】:

在调用os.stat()(或fstat/lstat)的结果上使用st_birthtime属性。

def get_creation_time(path):
    return os.stat(path).st_birthtime

您可以使用datetime.datetime.fromtimestamp() 将整数结果转换为日期时间对象。

由于某种原因,当第一次编写此答案时,我认为这在 Mac OS X 上不起作用,但我可能弄错了,现在它确实有效,即使使用旧版本的 Python 也是如此。旧答案如下。


使用ctypes 访问系统调用stat64(适用于Python 2.5+):

from ctypes import *

class struct_timespec(Structure):
    _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]

class struct_stat64(Structure):
    _fields_ = [
        ('st_dev', c_int32),
        ('st_mode', c_uint16),
        ('st_nlink', c_uint16),
        ('st_ino', c_uint64),
        ('st_uid', c_uint32),
        ('st_gid', c_uint32), 
        ('st_rdev', c_int32),
        ('st_atimespec', struct_timespec),
        ('st_mtimespec', struct_timespec),
        ('st_ctimespec', struct_timespec),
        ('st_birthtimespec', struct_timespec),
        ('dont_care', c_uint64 * 8)
    ]

libc = CDLL('libc.dylib') # or /usr/lib/libc.dylib
stat64 = libc.stat64
stat64.argtypes = [c_char_p, POINTER(struct_stat64)]

def get_creation_time(path):
    buf = struct_stat64()
    rv = stat64(path, pointer(buf))
    if rv != 0:
        raise OSError("Couldn't stat file %r" % path)
    return buf.st_birthtimespec.tv_sec

使用subprocess 调用stat 实用程序:

import subprocess

def get_creation_time(path):
    p = subprocess.Popen(['stat', '-f%B', path],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if p.wait():
        raise OSError(p.stderr.read().rstrip())
    else:
        return int(p.stdout.read())

【讨论】:

  • 完美!这正是我想要的。
  • 在 El Capitan 上,如果您收到 OSError: dlopen(libc.dylib, 6): image not found,您可能希望使用 libc = CDLL('/usr/lib/libc.dylib') 而不是 libc = CDLL('libc.dylib')
  • @ThomasOrozco 事实证明无论如何都有比 ctypes 更好的方法。
【解决方案2】:

ctime 在平台上有所不同:在某些系统(如 Unix)上是最后一次元数据更改的时间,而在其他系统(如 Windows)上是创建时间。这是因为 Unices 通常不会保留“原始”创建时间。

也就是说,您可以访问操作系统通过 stat 模块提供的所有信息。

stat 模块定义常量和函数用于解释 os.stat()、os.fstat() 和 os.lstat()(如果它们存在)的结果。有关 stat、fstat 和 lstat 调用的完整详细信息,请参阅您系统的文档。

stat.ST_CTIME
操作系统报告的“ctime”。在某些系统(如 Unix)上是最后一次元数据更改的时间,而在其他系统(如 Windows)上是创建时间(有关详细信息,请参阅平台文档)。

【讨论】:

  • 谢谢,但是... stat.ST_CTIME:操作系统报告的“ctime”。在某些系统(如 Unix)上是最后一次元数据更改的时间,而在其他系统(如 Windows)上是创建时间(有关详细信息,请参阅平台文档)。
  • @cefstat 这就是重点。一些系统(如 unice)只是提供“原始”创建时间。 python对此无能为力。
【解决方案3】:

由于缺乏好的实用程序,我创建了crtime

pip install crtime

然后你可以像这样使用它:

sudo crtime ./

将打印:

1552938281  /home/pascal/crtime/.gitignore
1552938281  /home/pascal/crtime/README.md
1552938281  /home/pascal/crtime/crtime
1552938281  /home/pascal/crtime/deploy.py
1552938281  /home/pascal/crtime/setup.cfg
1552938281  /home/pascal/crtime/setup.py
1552938961  /home/pascal/crtime/crtime.egg-info
1552939447  /home/pascal/crtime/.git
1552939540  /home/pascal/crtime/build
1552939540  /home/pascal/crtime/dist

请注意,对于大型目录,它会比有时提到的 xstat 快 1000 倍,因为这会创建一个临时文件,然后一次对所有文件执行 stat 调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多