Реализовать касание с помощью Python?
touch это утилита Unix, которая устанавливает время изменения и доступа к файлам в текущее время суток. Если файл не существует, он создается с разрешениями по умолчанию.
Как бы вы реализовали его как функцию Python? Постарайтесь быть кросс-платформенным и полным.
(текущие результаты Google для "python touch file" не так велики, но указывают на ОС.партнеров.)
11 ответов:
это пытается быть немного более свободным от гонки, чем другие решения. (Тег
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и изменить временную метку открытого файла handle, вместо того, чтобы открыть файл, а затем изменить временную метку на имя файла (который, возможно, был переименован). К сожалению, Python, похоже, не предоставляет способ звонитеfutimes, минуяctypesили аналогичные...
EDIT
как отмечает Нейт Парсонс, в Python 3.3 будет добавитьуказать файл дескриптора (при
os.supports_fd) для таких функций, какos.utime, который будет использоватьfutimessyscall вместоutimessyscall под капотом. Другими словами: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)
похоже, что это новое с Python 3.4 -
pathlib.from pathlib import Path Path('path/to/file.txt').touch()Это создаст
file.txtна пути.--
путь.touch (mode=0o777, exist_ok=True)
создать файл по указанному пути. Если задан режим, он объединяется со значением umask процесса для определения режима файла и флагов доступа. Если файл уже существует, функция завершается успешно, если exist_ok имеет значение true (и время его изменения равно обновлено до текущего времени), в противном случае возникает FileExistsError.
почему бы не попробовать это?:
import os def touch(fname): try: os.utime(fname, None) except OSError: open(fname, 'a').close()Я считаю, что это устраняет любые расовые условия, которые имеют значение. Если файл не существует, то будет сгенерировано исключение.
единственное возможное условие гонки здесь - Если файл создан до вызова open (), но после os.партнеров(). Но это не имеет значения, потому что в этом случае время модификации будет таким, как ожидалось, так как это должно было произойти во время вызова touch().
вот некоторый код, который использует 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)
- The
openгарантирует, что там есть файл- the
utimeгарантирует, что временные метки обновляютсятеоретически, возможно, кто-то удалит файл после
open, причинив партнеров, чтобы поднять исключение. Но, возможно, это нормально, так как случилось что-то плохое.
этот ответ совместим со всеми версиями начиная с Python-2.5 when keyword
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() calls2. Просто создайте файл, если он не существует
(не обновляет время)with open(fname, 'a'): # Create file if does not exist pass3. Просто обновить доступ к файлам / время изменения
(не создает файл, если он не существует)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 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.
может показаться логичным создать строку с нужными переменными и передать ее в ОС.система:
touch = 'touch ' + dir + '/' + fileName os.system(touch)этого недостаточно в ряде случаев (например,он не обрабатывает пробелы), поэтому не делайте этого.
более надежный метод заключается в использовании подпроцесса:
subprocess.call(['touch', os.path.join(dirname, fileName)])хотя это гораздо лучше, чем использовать подоболочку (с ОС.система), он по-прежнему подходит только для быстрых и грязных скриптов; используйте принятый ответ для кросс-платформенных программы.
" открыть (имя_файла, 'a').close () " не работал для меня в Python 2.7 на Windows. "ОС.utime (имя_файла, нет)" работал просто отлично.
кроме того, мне нужно было рекурсивно коснуться всех файлов в каталоге с датой старше некоторой даты. Я создал hte, основываясь на очень полезном ответе эфемера.
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)
Comments