Domanda

touch è un'utility Unix che imposta la modifica e tempi di accesso di file per l'ora del giorno. Se il file non esiste, viene creato con le autorizzazioni predefinite.

Come ti attuarla come una funzione Python? Cercate di essere cross-platform e completa.

(attuale risultati di Google per "file di python tocco" non è eccezionale, ma il punto di os.utime .)

È stato utile?

Soluzione

Sembra che questa è una novità come di Python 3.4 - pathlib .

from pathlib import Path

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

Questo creerà un file.txt nel percorso.

-

  

Path.touch (mode = 0o777, exist_ok = True)

     

Creare un file a questo dato percorso. Se viene dato modo, si combina con il valore di umask processo per determinare le bandiere modalità file e di accesso. Se il file esiste già, la funzione ha esito positivo se exist_ok è vero (e la sua data di modifica viene aggiornata al tempo corrente), in caso contrario FileExistsError è sollevata.

Altri suggerimenti

Questo cerca di essere un po 'più corsa libera rispetto alle altre soluzioni. (La parola chiave with è nuovo in Python 2.5.)

import os
def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)

o meno equivalente a questa.

import os
def touch(fname, times=None):
    fhandle = open(fname, 'a')
    try:
        os.utime(fname, times)
    finally:
        fhandle.close()

Ora, per davvero renderlo libero-gara, è necessario utilizzare futimes e cambiare il timestamp del filehandle aperto, invece di aprire il file e quindi modificando il timestamp sul nome del file (che è stato probabilmente rinominato). Purtroppo, Python non sembra fornire un modo per chiamare futimes senza passare attraverso ctypes o simili ...


Modifica

Come notato da Nate Parsons , Python 3.3 sarà href="http://docs.python.org/dev/library/os.html#path-fd" rel="noreferrer"> specificando un descrittore di file (quando os.supports_fd ) alle funzioni come os.utime , che utilizzerà lo syscall futimes invece del utimes syscall sotto il cofano. In altre parole:

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()

Perché non provare questo:?

import os

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

Credo che questo elimina qualsiasi condizione di competizione che conta. Se il file non esiste, allora verrà generata un'eccezione.

L'unica condizione possibile gara qui è se il file viene creato prima open () viene chiamato, ma dopo os.utime (). Ma questo non importa perché in questo caso sarà come previsto la data di modifica in quanto deve essere successo durante la chiamata al tatto ().

Ecco un po 'di codice che utilizza ctypes (testato solo su 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())

Questa risposta è compatibile con tutte le versioni dal Python-2.5 quando parola chiave with è stato rilasciato.

1. Creare file se non esiste + Imposta ora corrente
(Esattamente come il comando 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

Una versione più robusta:

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. Basta creare il file se non esiste
(Non aggiorna il tempo)

with open(fname, 'a'):  # Create file if does not exist
    pass

3. Basta aggiornare l'accesso ai file / orari modificati
(Non crea il file se non esistenti)

import os

try:
    os.utime(fname, None)  # Set access/modified times to now
except OSError:
    pass  # File does not exist (or no permission)

Utilizzando os.path.exists() non semplificare il codice:

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)

Bonus: Tempo di aggiornamento di tutti i file in una directory

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)

semplicistico:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • Il open garantisce che non v'è un file esiste
  • l'utime assicura che i timestamp vengono aggiornati

In teoria, è possibile che qualcuno eliminare il file dopo la open, causando utime a sollevare un'eccezione. Ma forse va bene, dal momento che qualcosa di brutto è accaduto.

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

Complex (possibilmente buggy):

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)

Questa prova per consentire anche l'impostazione di accesso o modifica di tempo, come GNU tocco.

Potrebbe sembrare logico per creare una stringa con le variabili desiderati, e passarlo al os.system:

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

Questo è inadeguata in diversi modi (ad esempio, non gestisce spazi bianchi), in modo da non farlo.

Un metodo più affidabile è quello di utilizzare sottoprocesso:

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

Anche se questo è molto meglio che usare una subshell (con os.system), è ancora adatto solo per gli script veloce-e-sporco; utilizzare la risposta accettata per i programmi multipiattaforma.

"open (nome_file, 'a'). Close ()" non ha funzionato per me in Python 2.7 su Windows. "Os.utime (nome_file, None)" ha lavorato bene.

Inoltre, ho avuto la necessità di toccare in modo ricorsivo tutti i file in una directory con una data più vecchio di una data. Ho creato hte seguente in base alla risposta molto utile di 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)

Perché non provare: newfile.py

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

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

python newfile.py foobar.txt

o

  

uso sottoprocesso:

import subprocess
subprocess.call(["touch", "barfoo.txt"])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top