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 が発生します。
これは、他のソリューションよりも少しレースフリーにしようとします。(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
は、ファイルを開いてからファイル名のタイムスタンプを変更するのではなく、開いているファイルハンドルのタイムスタンプを使用して変更する必要があります(名前が変更されている可能性があります)。futimes
残念ながら、Pythonは、通過することなく、または同様の方法で呼び出す方法を提供していないようですctypes
...
編集
Nate Parsonsが指摘しているように、Python 3.3は、ファイル記述子の指定(when )をなどの関数に追加 します。この関数は、内部でsyscallの代わりにsyscallを使用します。言い換えると: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()
これにより、重要な競合状態が解消されると思います。ファイルが存在しない場合は、例外がスローされます。
ここで考えられる唯一の競合状態は、open() が呼び出される前にファイルが作成されたが、os.utime() の後に作成された場合です。しかし、これは重要ではありません。なぜなら、この場合、修正時間は、touch() の呼び出し中に発生したに違いないため、予想どおりになるからです。
より低レベルのソリューションについては、使用できます
os.close(os.open("file.txt", os.O_CREAT))
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())
単純化:
def touch(fname):
open(fname, 'a').close()
os.utime(fname, None)
open
にファイルがあることを確認しますutime
により、タイムスタンプが確実に更新されます理論的には、誰かが の後にファイルを削除し、open
utime で例外が発生する可能性があります。しかし、何か悪いことが起こったので、間違いなくそれは問題ありません。
with open(file_name,'a') as f:
pass
目的の変数で文字列を作成し、それを os.system に渡すのは理にかなっているように思えるかもしれません。
touch = 'touch ' + dir + '/' + fileName
os.system(touch)
これは多くの点で不適切なので (たとえば、空白を処理しない)、使用しないでください。
より堅牢な方法は、 subprocess を使用することです:
subprocess.call(['touch', os.path.join(dirname, fileName)])
これは、サブシェル (os.system を使用) を使用するよりもはるかに優れていますが、依然として、迅速かつダーティなスクリプトにしか適していません。クロスプラットフォーム プログラムに受け入れられた回答を使用します。
試してみませんか: 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"])