touch
是一种Unix实用程序,它将文件的修改和访问时间设置为当天的当前时间。如果该文件不存在,则会使用默认权限创建。
您如何将其实现为Python函数?请尝试跨平台并完整。
(当前搜索“python touch file”的 Google 结果并不理想,但指向 os.utime。)
看起来这是Python 3.4以后的新功能 - pathlib
。
from pathlib import Path
Path('path/to/file.txt').touch()
这将在路径上创建一个file.txt
文件。
--
Path.touch(mode=0o777, exist_ok=True)
在给定的路径上创建一个文件。如果提供了mode,则与进程的umask值结合使用以确定文件模式和访问标志。如果文件已经存在且exist_ok为true,则函数将成功(并将其修改时间更新为当前时间),否则会引发FileExistsError异常。
pip install pathlib
- Andre MirasPath('/some/path').mkdir()
。然后再执行 touch()
操作。 - JacobIRRpathlib2
而不是pathlib
,因为pathlib
现在仅用于修复漏洞。因此,在Python 2.7上:请运行pip install pathlib2
,然后导入Path
时运行from pathlib2 import Path
。 - Ian Lin777
而不是像644
这样更保守的权限设置。 - zachaysanPath("...").touch()
不会返回任何值,所以如果你想在 .touch()
之前存储 Path("...")
,就需要将其存储到一个变量中。 - Joe Sadoski这个解决方案试图比其他解决方案更加避免竞争条件。(with
关键词在Python 2.5中是新的。)
import os
def touch(fname, times=None):
with open(fname, 'a'):
os.utime(fname, times)
大致等同于这个。
import os
def touch(fname, times=None):
fhandle = open(fname, 'a')
try:
os.utime(fname, times)
finally:
fhandle.close()
现在,为了确保它是无竞争的,您需要使用futimes
并更改打开文件句柄的时间戳,而不是打开文件,然后更改文件名(可能已被重命名)的时间戳。不幸的是,Python似乎没有提供一种调用futimes
而不经过ctypes
或类似方式的方法...
编辑
如Nate Parsons所指出的,Python 3.3将添加指定文件描述符(当os.supports_fd
时),对诸如os.utime
之类的函数进行操作,这将在底层使用futimes
系统调用而不是utimes
系统调用。换句话说:
import os
def touch(fname, mode=0o666, dir_fd=None, **kwargs):
flags = os.O_CREAT | os.O_APPEND
with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f:
os.utime(f.fileno() if os.utime in os.supports_fd else fname,
dir_fd=None if os.supports_fd else dir_fd, **kwargs)
def touch(fname):
if os.path.exists(fname):
os.utime(fname, None)
else:
open(fname, 'a').close()
open(fname, 'a').close()
不会改变 atime。 - SilentGhostos.utime()
保留在那里。 - Greg Hewgill为什么不试试这个呢?:
import os
def touch(fname):
try:
os.utime(fname, None)
except OSError:
open(fname, 'a').close()
我相信这消除了任何重要的竞争条件。如果文件不存在,则将抛出异常。
此处唯一可能存在的竞争条件是,在调用open()之前但在os.utime()之后创建文件。但是,这并不重要,因为在这种情况下,修改时间将符合预期,因为它必须发生在touch()调用期间。
自Python-2.5版本发布以来,本回答适用于所有版本,当时关键字with
已经发布。
1. 如果不存在则创建文件 + 设置当前时间
(与touch
命令完全相同)
import os
fname = 'directory/filename.txt'
with open(fname, 'a'): # Create file if does not exist
os.utime(fname, None) # Set access/modified times to now
# May raise OSError if file does not exist
更健壮的版本:
import os
with open(fname, 'a'):
try: # Whatever if file was already existing
os.utime(fname, None) # => Set current time anyway
except OSError:
pass # File deleted between open() and os.utime() calls
2. 只需在文件不存在时创建该文件
(不更新时间)
with open(fname, 'a'): # Create file if does not exist
pass
3. 仅更新文件的访问/修改时间
(如果文件不存在,则不创建文件)
import os
try:
os.utime(fname, None) # Set access/modified times to now
except OSError:
pass # File does not exist (or no permission)
使用os.path.exists()
并不能简化代码:
from __future__ import (absolute_import, division, print_function)
import os
if os.path.exists(fname):
try:
os.utime(fname, None) # Set access/modified times to now
except OSError:
pass # File deleted between exists() and utime() calls
# (or no permission)
奖励:更新目录中所有文件的修改时间
from __future__ import (absolute_import, division, print_function)
import os
number_of_files = 0
# Current directory which is "walked through"
# | Directories in root
# | | Files in root Working directory
# | | | |
for root, _, filenames in os.walk('.'):
for fname in filenames:
pathname = os.path.join(root, fname)
try:
os.utime(pathname, None) # Set access/modified times to now
number_of_files += 1
except OSError as why:
print('Cannot change time of %r because %r', pathname, why)
print('Changed time of %i files', number_of_files)
from ctypes import *
libc = CDLL("libc.so.6")
# struct timespec {
# time_t tv_sec; /* seconds */
# long tv_nsec; /* nanoseconds */
# };
# int futimens(int fd, const struct timespec times[2]);
class c_timespec(Structure):
_fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]
class c_utimbuf(Structure):
_fields_ = [('atime', c_timespec), ('mtime', c_timespec)]
utimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))
futimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))
# from /usr/include/i386-linux-gnu/bits/stat.h
UTIME_NOW = ((1l << 30) - 1l)
UTIME_OMIT = ((1l << 30) - 2l)
now = c_timespec(0,UTIME_NOW)
omit = c_timespec(0,UTIME_OMIT)
# wrappers
def update_atime(fileno):
assert(isinstance(fileno, int))
libc.futimens(fileno, byref(c_utimbuf(now, omit)))
def update_mtime(fileno):
assert(isinstance(fileno, int))
libc.futimens(fileno, byref(c_utimbuf(omit, now)))
# usage example:
#
# f = open("/tmp/test")
# update_mtime(f.fileno())
简单易懂:
def touch(fname):
open(fname, 'a').close()
os.utime(fname, None)
open
确保文件存在utime
确保时间戳更新理论上,有可能在 open
后删除文件,导致 utime
抛出异常。但可以认为这是可以接受的,因为确实发生了一些不好的事情。
with open(file_name,'a') as f:
pass
with open(fn,'a'): pass
或替代方案open(fn, 'a').close()
不会更改修改时间。在我的平台上,这些解决方案只会在文件不存在时创建一个空文件。 :-/ - oHoimport os
def func(filename):
if os.path.exists(filename):
os.utime(filename)
else:
with open(filename,'a') as f:
pass
os.utime(filename,(atime,mtime))
在这里,atime和mtime都应该是int/float类型,并且应该等于您想要设置的时间的秒数。
touch
功能,而不是如何从头开始重新实现它。对于那些人来说,最好向下滚动到pathlib
解决方案。尽管现在内置了此功能,但是这个答案在“python touch file”的谷歌排名上比相关文档更高。 - Miles