使用Python实现触摸?

its*_*dok 298 python utility

touch是一个Unix实用程序,它将文件的修改和访问时间设置为当前时间.如果该文件不存在,则使用默认权限创建该文件.

你如何将它作为Python函数实现?尝试跨平台和完整.

(目前Google搜索"python touch file"的结果并不是那么好,但是指向os.utime.)

eph*_*ent 234

这试图比其他解决方案更无竞赛.(with关键字是Python 2.5中的新增内容.)

import os
def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)
Run Code Online (Sandbox Code Playgroud)

大致相当于此.

import os
def touch(fname, times=None):
    fhandle = open(fname, 'a')
    try:
        os.utime(fname, times)
    finally:
        fhandle.close()
Run Code Online (Sandbox Code Playgroud)

现在,要真正使其无竞争,您需要使用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)
Run Code Online (Sandbox Code Playgroud)


voi*_*ogo 227

从Python 3.4开始看起来这是新的 - pathlib.

from pathlib import Path

Path('path/to/file.txt').touch()
Run Code Online (Sandbox Code Playgroud)

这将file.txt在路径上创建一个.

-

Path.touch(mode = 0o777,exist_ok = True)

在此给定路径创建文件.如果给出了mode,则将其与进程'umask值组合以确定文件模式和访问标志.如果文件已经存在,则如果exist_ok为true(并且其修改时间更新为当前时间),则函数成功,否则引发FileExistsError.

  • 自我注意:如果包含要进行touch()编辑的文件的目录尚不存在,请使用Path('/ some / path')。mkdir()。 (5认同)
  • 我很惊讶它默认为“777”,而不是像“644”这样更保守的东西。 (3认同)
  • 在Python2.7上:`pip install pathlib` (2认同)
  • 我认为我们应该使用 `pathlib2` 而不是 `pathlib`,因为 `pathlib` 现在只是错误修复。因此,在 Python 2.7 上:`pip install pathlib2` 然后是 `from pathlib2 import Path`。 (2认同)
  • 我想指出 `Path("...").touch()` 不返回任何内容,因此如果您可能想在 `.touch()` 之前将 `Path("...")` 存储到变量中荷兰国际集团它。 (2认同)

Sil*_*ost 41

def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'a').close()
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案中存在潜在的竞争条件:如果该文件不存在,并且在此函数到达`open()`调用之前由另一个进程创建,则该文件的内容将被截断.建议使用模式''a'来代替. (24认同)
  • 同意.正确的解决方案就是:def touch(fname):open(fname,'wa').close() (7认同)
  • 为什么不打开以确保它存在,然后打电话给utime? (4认同)

jco*_*and 26

为什么不尝试这个?:

import os

def touch(fname):
    try:
        os.utime(fname, None)
    except OSError:
        open(fname, 'a').close()
Run Code Online (Sandbox Code Playgroud)

我相信这可以消除任何重要的竞争条件.如果文件不存在,则抛出异常.

这里唯一可能的竞争条件是文件是在调用open()之前创建的,而是在os.utime()之后创建的.但这并不重要,因为在这种情况下,修改时间将如预期的那样,因为它必须在调用touch()期间发生.


eug*_*eug 8

这里有一些使用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())
Run Code Online (Sandbox Code Playgroud)


hei*_*ner 8

对于更底层的解决方案,可以使用

os.close(os.open("file.txt", os.O_CREAT))
Run Code Online (Sandbox Code Playgroud)

  • 从文档“os.O_CREAT - 如果文件不存在则创建文件” (2认同)

oli*_*bre 7

自从发布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
Run Code Online (Sandbox Code Playgroud)

一个更强大的版本:

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
Run Code Online (Sandbox Code Playgroud)

2.如果不存在,则仅创建文件
(不更新时间)

with open(fname, 'a'):  # Create file if does not exist
    pass
Run Code Online (Sandbox Code Playgroud)

3.只需更新文件访问/修改时间
(如果不存在则不创建文件)

import os

try:
    os.utime(fname, None)  # Set access/modified times to now
except OSError:
    pass  # File does not exist (or no permission)
Run Code Online (Sandbox Code Playgroud)

使用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)
Run Code Online (Sandbox Code Playgroud)

奖励:目录中所有文件的更新时间

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)
Run Code Online (Sandbox Code Playgroud)


its*_*dok 5

简单:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
Run Code Online (Sandbox Code Playgroud)
  • open确保有一个文件存在
  • utime该时间戳更新,确保

从理论上讲,有人可能会在 之后删除文件open,从而导致 utime 引发异常。但可以说这没关系,因为确实发生了一些不好的事情。


Mat*_*att 5

with open(file_name,'a') as f: 
    pass
Run Code Online (Sandbox Code Playgroud)