Внедрить Touch с помощью Python?
touch
- это утилита Unix, которая устанавливает время изменения файлов и время доступа к текущему времени суток. Если файл не существует, он создается с разрешениями по умолчанию.
Как бы вы реализовали его как функцию Python? Постарайтесь быть кросс-платформенными и полными.
(Текущие результаты Google для "файла касания python" не так уж хороши, но указывают на os.utime.)
Ответы
Ответ 1
Похоже, что это новшество по сравнению с Python 3.4 - pathlib
.
from pathlib import Path
Path('path/to/file.txt').touch()
Это создаст file.txt
на пути.
-
Path.touch(mode = 0o777, exist_ok = True)
Создайте файл по данному пути. Если задан режим, он объединяется со значением umask процесса, чтобы определить режим файла и флаги доступа. Если файл уже существует, функция будет успешной, если exist_ok истинно (и время его модификации обновляется до текущего времени), в противном случае FileExistsError будет поднят.
Ответ 2
Это попытка быть немного более свободной от гонки, чем другие решения. (Ключевое слово 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 будет добавить указание файлового дескриптора (когда os.supports_fd
) для таких функций, как os.utime
, который будет использовать syscall futimes
вместо syscall 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)
Ответ 3
def touch(fname):
if os.path.exists(fname):
os.utime(fname, None)
else:
open(fname, 'a').close()
Ответ 4
Почему бы не попробовать это?:
import os
def touch(fname):
try:
os.utime(fname, None)
except OSError:
open(fname, 'a').close()
Я считаю, что это устраняет любое состояние гонки, которое имеет значение. Если файл не существует, будет выбрано исключение.
Единственное возможное условие гонки здесь - это если файл создается до вызова функции open(), но после os.utime(). Но это не имеет значения, потому что в этом случае время модификации будет таким, как ожидалось, поскольку оно должно было произойти во время вызова touch().
Ответ 5
Вот некоторый код, который использует 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())
Ответ 6
This answer is compatible with all versions since Python-2.5 when keyword [TG40] has been released.
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)
Ответ 7
Simplistic:
def touch(fname):
open(fname, 'a').close()
os.utime(fname, None)
-
open
гарантирует наличие там файла
-
utime
гарантирует, что отметки времени обновляются
Теоретически, возможно, кто-то удалит файл после open
, вызывая утилизацию для создания исключения. Но, возможно, это нормально, так как произошло что-то плохое.
Ответ 8
with open(file_name,'a') as f:
pass
Ответ 9
Сложный (возможно, багги):
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.
Ответ 10
Кажется логичным создать строку с нужными переменными и передать ее в os.system:
touch = 'touch ' + dir + '/' + fileName
os.system(touch)
Это неадекватно несколькими способами (например, он не обрабатывает пробелы), поэтому не делайте этого.
Более надежным методом является использование подпроцесса:
subprocess.call(['touch', os.path.join(dirname, fileName)])
Хотя это намного лучше, чем использование подоболочки (с os.system), оно по-прежнему подходит только для быстрых и грязных скриптов; используйте принятый ответ для кросс-платформенных программ.
Ответ 11
"open (имя_файла, 'a'). close()" не работает для меня в Python 2.7 на Windows. "os.utime(имя_файла, нет)" отлично работает.
Кроме того, мне пришлось рекурсивно обращаться ко всем файлам в каталоге с датой, которая старше даты. Я создал hte follow, основанный на эфемерном очень полезном ответе.
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)
Ответ 12
Почему бы тебе не попробовать:
newfile.py
#!/usr/bin/env python
import sys
inputfile = sys.argv[1]
with open(inputfile, 'w') as file:
pass
python newfile.py foobar.txt
или
use subprocess:
import subprocess
subprocess.call(["touch", "barfoo.txt"])