web-dev-qa-db-ja.com

Pythonを使用してタッチを実装しますか?

touchは、ファイルの変更時刻とアクセス時刻を現在の時刻に設定するUnixユーティリティです。ファイルが存在しない場合、デフォルトの権限で作成されます。

Python関数としてどのように実装しますか?クロスプラットフォームになり、完了してください。

(「python touch file」の現在のGoogle結果はそれほど素晴らしいものではありませんが、 os.utime を指します。)

267
itsadok

これは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が送出されます。

182
voidnologo

これは、他のソリューションよりも少し人種を排除しようとします。 (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は addファイル記述子の指定 (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)
231
ephemient
def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'a').close()
38
SilentGhost

これを試してみませんか?:

import os

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

これにより、重要な競合状態が解消されます。ファイルが存在しない場合、例外がスローされます。

ここで唯一可能な競合状態は、open()が呼び出される前に、os.utime()の後にファイルが作成される場合です。ただし、この場合、touch()の呼び出し中に変更が行われたはずなので、変更時間は予想どおりになるため、これは重要ではありません。

25
jcoffland

以下に、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())
8
eug

この答えは、キーワード with がリリースされたPython-2.5以降のすべてのバージョンと互換性があります。

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)
6
olibre
with open(file_name,'a') as f: 
    pass
3
Matt

単純化:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • openは、そこにファイルがあることを保証します
  • utimeは、タイムスタンプが更新されることを保証します

理論的には、誰かがopenの後にファイルを削除し、utimeが例外を発生させる可能性があります。しかし、おそらく悪いことは起こったので、それは大丈夫です。

3
itsadok

「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)
1
cadvena

複雑(おそらくバグあり):

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などのアクセス時間または変更時間の設定も許可されます。

1
itsadok

目的の変数を使用して文字列を作成し、os.systemに渡すことは論理的に思えるかもしれません。

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

これは、いくつかの点で不十分です(たとえば、空白を処理しません)。

より堅牢な方法は、サブプロセスを使用することです:

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

これは(os.systemを使用して)サブシェルを使用するよりもはるかに優れていますが、それでも、迅速で汚いスクリプトにのみ適しています。クロスプラットフォームプログラムに受け入れられた回答を使用します。

1
Manoj