问题:使用Python实现触摸?
touch
是Unix实用程序,用于将文件的修改和访问时间设置为当前时间。如果文件不存在,则使用默认权限创建。
您如何将其实现为Python函数?尝试跨平台并完善。
(Google当前针对“ python触摸文件”的搜索结果并不理想,但指向os.utime。)
回答 0
看起来这是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。
回答 1
与其他解决方案相比,这要使比赛更加自由。(该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将为诸如之类的函数添加 指定文件描述符(when os.supports_fd
)os.utime
,该函数将使用futimes
syscall而不是内部的utimes
syscall。换一种说法:
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)
回答 2
def touch(fname):
if os.path.exists(fname):
os.utime(fname, None)
else:
open(fname, 'a').close()
回答 3
为什么不试试呢?:
import os
def touch(fname):
try:
os.utime(fname, None)
except OSError:
open(fname, 'a').close()
我相信这可以消除任何重要的比赛条件。如果该文件不存在,则将引发异常。
唯一可能的竞争条件是,如果文件是在调用open()之前但在os.utime()之后创建的。但这无关紧要,因为在这种情况下,修改时间将是预期的,因为修改时间必须在调用touch()的过程中发生。
回答 4
以下是一些使用ctypes的代码(仅在Linux上经过测试):
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())
回答 5
自从发布Python-2.5关键字以来,此答案与所有版本兼容with
。
1.如果不存在则创建文件+设置当前时间
(与command完全相同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)
回答 6
with open(file_name,'a') as f:
pass
回答 7
简单化:
def touch(fname):
open(fname, 'a').close()
os.utime(fname, None)
- 在
open
确保有一个文件存在 - 在
utime
该时间戳更新,确保
从理论上讲,有人可能会在之后删除文件open
,从而导致utime引发异常。但是可以说是可以的,因为确实发生了一些不好的事情。
回答 8
复杂(可能是越野车):
def utime(fname, atime=None, mtime=None)
if type(atime) is tuple:
atime, mtime = atime
if atime is None or mtime is None:
statinfo = os.stat(fname)
if atime is None:
atime = statinfo.st_atime
if mtime is None:
mtime = statinfo.st_mtime
os.utime(fname, (atime, mtime))
def touch(fname, atime=None, mtime=None):
if type(atime) is tuple:
atime, mtime = atime
open(fname, 'a').close()
utime(fname, atime, mtime)
这也尝试允许设置访问或修改时间,例如GNU touch。
回答 9
用所需的变量创建一个字符串并将其传递给os.system似乎是合乎逻辑的:
touch = 'touch ' + dir + '/' + fileName
os.system(touch)
这在许多方面都是不够的(例如,它不处理空格),因此请不要这样做。
一种更可靠的方法是使用子过程:
subprocess.call(['touch', os.path.join(dirname, fileName)])
尽管这比使用子shell(使用os.system)要好得多,但它仍然仅适用于快捷脚本。将接受的答案用于跨平台程序。
回答 10
“ open(file_name,’a’)。close()”在Windows上的Python 2.7中对我不起作用。“ os.utime(file_name,None)”工作得很好。
另外,我还需要递归地触摸目录中某个日期早于某个日期的所有文件。我根据ephemient的非常有用的回复创建了以下关注者。
def touch(file_name):
# Update the modified timestamp of a file to now.
if not os.path.exists(file_name):
return
try:
os.utime(file_name, None)
except Exception:
open(file_name, 'a').close()
def midas_touch(root_path, older_than=dt.now(), pattern='**', recursive=False):
'''
midas_touch updates the modified timestamp of a file or files in a
directory (folder)
Arguements:
root_path (str): file name or folder name of file-like object to touch
older_than (datetime): only touch files with datetime older than this
datetime
pattern (str): filter files with this pattern (ignored if root_path is
a single file)
recursive (boolean): search sub-diretories (ignored if root_path is a
single file)
'''
# if root_path NOT exist, exit
if not os.path.exists(root_path):
return
# if root_path DOES exist, continue.
else:
# if root_path is a directory, touch all files in root_path
if os.path.isdir(root_path):
# get a directory list (list of files in directory)
dir_list=find_files(root_path, pattern='**', recursive=False)
# loop through list of files
for f in dir_list:
# if the file modified date is older thatn older_than, touch the file
if dt.fromtimestamp(os.path.getmtime(f)) < older_than:
touch(f)
print "Touched ", f
# if root_path is a file, touch the file
else:
# if the file modified date is older thatn older_than, touch the file
if dt.fromtimestamp(os.path.getmtime(f)) < older_than:
touch(root_path)
回答 11
你为什么不尝试:newfile.py
#!/usr/bin/env python
import sys
inputfile = sys.argv[1]
with open(inputfile, 'w') as file:
pass
python newfile.py foobar.txt
要么
使用子过程:
import subprocess
subprocess.call(["touch", "barfoo.txt"])
回答 12
以下内容就足够了:
import os
def func(filename):
if os.path.exists(filename):
os.utime(filename)
else:
with open(filename,'a') as f:
pass
如果要设置触摸的特定时间,请按以下方式使用os.utime:
os.utime(filename,(atime,mtime))
在这里,atime和mtime都应为int / float,并且应等于以秒为单位的纪元时间到您要设置的时间。
回答 13
如果您不介意尝试,那么…
def touch_dir(folder_path):
try:
os.mkdir(folder_path)
except FileExistsError:
pass
不过要注意的一件事是,如果存在一个具有相同名称的文件,则该文件将无法工作,并且将以静默方式失败。
回答 14
write_text()
从pathlib.Path
可以使用。
>>> from pathlib import Path
>>> Path('aa.txt').write_text("")
0