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

您将如何将其实现为 Python 函数?尝试跨平台且完整。

(当前“python touch file”的 Google 结果不是很好,但指向 操作系统utime.)

有帮助吗?

解决方案

看起来这是新的像Python 3.4 - pathlib

from pathlib import Path

Path('path/to/file.txt').touch()

这将在路径创建file.txt

-

  

Path.touch(模式= 0o777,exist_ok =真)

     

创建在此给定的路径中的文件。如果给出模式,它与进程的umask值相结合,以确定文件模式和访问标志。如果该文件已经存在,如果功能是exist_ok真(其修改时间更新为当前时间),否则FileExistsError提高成功。

其他提示

这试图比其他解决方案更加无竞争。(这 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 或类似...


编辑

正如所指出的 内特·帕森斯, 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()

为什么不试试这个:

import os

def touch(fname):
    try:
        os.utime(fname, None)
    except OSError:
        open(fname, 'a').close()

我相信这消除了任何重要的竞争条件。如果该文件不存在,一个异常将被抛出。

这里唯一可能的竞争条件是,如果在开放之前创建的文件()被调用,但os.utime后()。但是,因为在这种情况下,修改时间会如预期,因为它必须在通话过程中发生碰这个无所谓()。

下面是一个使用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())

这个答案与 Python-2.5 以来的所有版本兼容 when 关键字 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)

简单:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • open 确保有一个文件里
  • utime 确保时间戳是更新

从理论上讲,它可能有人会删除了该文件后 open, ,造成utime提出一个例外。但可以说这是确定的,因为坏事发生了。

with open(file_name,'a') as f: 
    pass

复合(可能车):

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触摸。

这似乎逻辑以产生具有所希望的变量的字符串,并把它传递给使用os.system:

touch = 'touch ' + dir + '/' + fileName
os.system(touch)

这是在许多方面(例如,它不能处理的空白)不足,所以不这样做。

一个更鲁棒的方法是使用子过程:

subprocess.call(['touch', os.path.join(dirname, fileName)])

虽然这比使用子外壳(与使用os.system),它仍然是仅适合于快速和脏脚本好得多;使用接受的答案为跨平台的程序。

“打开(FILE_NAME, 'A')。关闭()” 并没有为我在Python 2.7在Windows上运行。 “os.utime(FILE_NAME,无)” 工作得很好。

另外,我有一个需要递归触摸的所有目录中的文件比一些日期的日期。我创建兴田基于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)

为什么不试试: newfile.py

#!/usr/bin/env python
import sys
inputfile = sys.argv[1]

with open(inputfile, 'w') as file:
    pass
  

蟒newfile.py foobar.txt

  

使用子过程:

import subprocess
subprocess.call(["touch", "barfoo.txt"])
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top