17

是否可以检查文件是否已在 python 中被删除或重新创建?

例如,如果您open("file")在脚本中执行了 a ,然后在该文件仍处于打开状态时执行rm file; touch file;,那么即使旧文件已被删除,该脚本仍将保留对旧文件的引用。

4

3 回答 3

23

您应该fstat打开文件的文件描述符。

>>> import os
>>> f = open("testdv.py")
>>> os.fstat(f.fileno())
posix.stat_result(st_mode=33188, st_ino=1508053, st_dev=65027L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1107, st_atime=1349180541, st_mtime=1349180540, st_ctime=1349180540)
>>> os.fstat(f.fileno()).st_nlink
1

好的,这个文件有一个链接,所以文件系统中有一个名称。现在删除它:

>>> os.unlink("testdv.py")
>>> os.fstat(f.fileno()).st_nlink
0

没有更多的链接,所以我们有一个“匿名文件”,只要我们打开它,它就会一直保持活动状态。创建同名的新文件对旧文件没有影响:

>>> g = open("testdv.py", "w")
>>> os.fstat(g.fileno()).st_nlink
1
>>> os.fstat(f.fileno()).st_nlink
0

当然,st_nlink有时可能是>1最初的,因此检查为零并不完全可靠(尽管在受控设置中,它可能已经足够好了)。stat相反,您可以通过比较结果来验证您最初打开的路径中的文件是否与您拥有文件描述符的文件相同:

>>> os.stat("testdv.py") == os.fstat(f.fileno())
False
>>> os.stat("testdv.py") == os.fstat(g.fileno())
True

(如果您希望这是 100% 正确,那么您应该只比较结果中的st_devst_ino字段stat,因为其他字段,st_atime尤其是在调用之间可能会发生变化。)

于 2012-10-02T13:01:50.080 回答
5

是的。使用os.stat()功能检查文件长度。如果长度为零(或函数返回错误“找不到文件”),则有人删除了该文件。

或者,您可以在每次需要向其中写入内容时打开+写入+关闭文件。缺点是打开文件是一个非常慢的操作,所以如果您需要写入大量数据,这是不可能的。

为什么?因为新文件不是您打开的文件。简而言之,Unix 文件系统有两个层次。一级是目录项(即文件名、文件大小、修改时间、指向数据的指针),二级是文件数据。

当您打开一个文件时,Unix 使用该名称来查找文件数据。之后,它只在第二级运行——对目录条目的更改对任何打开的“文件句柄”都没有影响。这正是您可以删除目录条目的原因:您的程序没有使用它。

使用 时os.stat(),您不会查看文件数据,而是再次查看目录条目。

从积极的方面来说,这允许您创建除了您的程序之外没有人可以看到的文件:打开文件,删除它然后使用它。由于该文件没有目录条目,因此没有其他程序可以访问该数据。

消极的一面是,你不能轻易解决你所遇到的问题。

于 2012-10-02T12:40:37.440 回答
3

是的——您可以使用该inotify工具检查文件更改等。还有一个 Python绑定。使用 inotify 您可以监视文件或目录的文件系统活动。从手册中可以检测到以下事件:

IN_ACCESS         File was accessed (read) (*).
IN_ATTRIB         Metadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*).
IN_CLOSE_WRITE    File opened for writing was closed (*).
IN_CLOSE_NOWRITE  File not opened for writing was closed (*).
IN_CREATE         File/directory created in watched directory (*).
IN_DELETE         File/directory deleted from watched directory (*).
IN_DELETE_SELF    Watched file/directory was itself deleted.
IN_MODIFY         File was modified (*).
IN_MOVE_SELF      Watched file/directory was itself moved.
IN_MOVED_FROM     File moved out of watched directory (*).
IN_MOVED_TO       File moved into watched directory (*).
IN_OPEN           File was opened (*).

从这里你可以用谷歌搜索自己的解决方案,但我认为你明白了整体的想法。当然,这可能仅适用于 Linux,但根据您的问题,我假设您正在使用它(参考rmtouch)。

于 2012-10-02T12:49:04.977 回答