Python kullanarak dokunuş uygulanıyor mu?


352

touchdosyaların değişiklik ve erişim saatlerini günün geçerli saatine ayarlayan bir Unix yardımcı programıdır. Dosya yoksa, varsayılan izinlerle oluşturulur.

Python işlevi olarak nasıl uygularsınız? Çapraz platform ve tam olmaya çalışın.

("Python dokunma dosyası" için geçerli Google sonuçları o kadar iyi değil, os.utime'ı gösteriyor .)


4
Lütfen bu işlevselliğin Python stdlib'in içine yerleştirildiğini kabul edin.
Miles

@Miles Kabul edilen cevap, sorunun tam olarak ne istediğini yapar - işlevi bir kitaplık kullanmak yerine Python'da uygular.
strafor

5
@styrofoamfly standart kütüphanesi olan Python parçası. Askerlerin gerçekten bilmek istedikleri sorunun (ve bu soruya Google aracılığıyla gelen çoğu insanın) touchPython programlarında nasıl benzer bir işlevsellik elde edileceği, sıfırdan nasıl yeniden uygulanacağı değil; bu kişilere en iyi şekilde, pathlibçözüme inerek hizmet edilir . Şu anda yerleşik olmasına rağmen, bu yanıt "python touch dosyası" için Google dokümanlarında ilgili dokümanlara göre çok daha iyi .
Miles

@miles Python 2 (ne yazık ki) hala 3'ten daha yaygın olarak kullanılıyor, bu yüzden kabul edilen cevabın hala daha alakalı olduğunu düşünüyorum. Ama yorumunuz insanları ikinci cevaba yönlendirmek için iyi bir iş çıkarıyor.
itsadok

6
Python 2, bu yılın sonunda EOL.
Max Gasner

Yanıtlar:


304

Python 3.4 - 'den yeni gibi görünüyor pathlib.

from pathlib import Path

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

Bu file.txt, yolda bir oluşturur.

-

Path.touch (mod = 0o777, exist_ok = Doğru)

Bu verilen yolda bir dosya oluşturun. Mod verilirse, dosya modunu ve erişim bayraklarını belirlemek için işlemin umask değeri ile birleştirilir. Dosya zaten varsa, işlev_varsa_ok true olursa (ve değiştirme zamanı geçerli saate güncellenirse) başarılı olur, aksi takdirde FileExistsError yükseltilir.


3
Python2.7'de:pip install pathlib
Andre Miras

8
self to note: Path('/some/path').mkdir()düzenlenecek dosyayı içeren dizin touch()henüz mevcut değilse kullanın.
JacobIRR

1
Bunun pathlib2yerine kullanmamız gerektiğini düşünüyorum pathlibçünkü pathlibartık sadece bugfix. Bu nedenle, Python 2.7: pip install pathlib2ve sonra from pathlib2 import Path.
Ian Lin

@IanLin Standart kitaplığın zaten desteklediği bir şey yapmak için kitaplık yüklemek için çok az neden vardır. Eğer karıştırıyorsun bitbucket.org/pitrou/pathlib/src/default ile docs.python.org/dev/library/pathlib.html ?
Michael Mrozek

Bu yorum, Andre'nin standart kütüphaneye sahip olmayan Python 2.7 hakkında konuştuğunu söylüyor. Belgeyi pypi.org/project/pathlib2 adresinden okumaktan çekinmeyin
Ian Lin

242

Bu, diğer çözümlerden biraz daha ırksız olmaya çalışıyor. ( withAnahtar kelime Python 2.5'te yenidir.)

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

Kabaca buna eşdeğer.

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

Şimdi, gerçekten yarıştan bağımsız hale getirmek için futimes, dosyayı açmak ve daha sonra dosya adındaki (yeniden adlandırılmış olabilir) zaman damgasını değiştirmek yerine, açık dosya sapının zaman damgasını kullanmanız ve değiştirmeniz gerekir . Ne yazık ki, Python veya benzeri futimesolmadan arama yapmak için bir yol gibi görünmüyor ctypes...


DÜZENLE

Nate Parsons tarafından belirtildiği gibi , Python 3.3, gibi fonksiyonlara bir dosya tanımlayıcı (ne zaman ) belirterek ekleyecektir , bu da kaputun altındaki sistem çağrısı yerine sistem çağrısını kullanacaktır . Diğer bir deyişle:os.supports_fdos.utimefutimesutimes

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)

Bu gerçek çözümdür - ve futimes () mevcut değilse, coreutils'deki touch (1) bunu yapar. futimes taşınabilir bir işlev değildir ve daha eski 2.6 Linux çekirdeğinde bile mevcut değildir, bu nedenle ENOSYS ile uğraşmanız ve kullansanız bile tekrar kullanmaya başlamanız gerekir.
Glenn Maynard

(Yukarıdaki düzeltme yazım hatası: "Bu" = açık ("a") + futimes.) Neyse ki, futimes kullanmama yarış koşulunun gerçekten önemli olduğu bir durumu düşünmek zor. Sonuçta ortaya çıkabilecek "yanlış" durum, open () ve utime () arasında yeniden adlandırılan dosyadır; bu durumda yeni bir dosya oluşturmaz veya eskisine dokunmazsınız. Bu önemli olabilir, ancak çoğu zaman olmaz.
Glenn Maynard

cygwin touch sihrini salt okunur dosyalarda yapabilir, ancak bu kod yapamaz. Ancak ben denemek ile çevrelemek işe yarıyor gibi: <code> IOError gibi e: (e.errno kontrol edin) os.utime (dosya adı, kez)
dash-tom-bang

FYI, 3.3'te futimes eklendi gibi görünüyor
Nate Parsons

Not: yerleşik fileişlev Python 3'ten kaldırılmıştır ve openbunun yerine kullanılması gerekir. Bunu tamamen kaçırdım çünkü kullandığım editörün sözdizimi vurgulaması (gedit) hala Python 2'yi hedefliyor.
Bart

42
def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'a').close()

24
Bu çözümde olası bir yarış koşulu vardır: Dosya yoksa ve bu işlev open()çağrıya ulaşmadan önce başka bir işlem tarafından oluşturulursa , dosyanın içeriği kesilir. 'a'Bunun yerine modu kullanmanızı öneririz.
Greg Hewgill

7
Kabul. Doğru çözüm sadece: def touch (fname): open (fname, 'wa').
Close

@Greg, potansiyel yarış koşulu sorununu çözerken, open(fname, 'a').close()zaman değiştirmeyecek.
SilentGhost

@SilentGhost: Bu doğru, ama sorun değil çünkü dosya varsa yeni oluşturuldu. Elbette os.utime()önceden varolan dosyalar için aramayı orada bırakacaksınız .
Greg Hewgill

4
Neden sadece var olduğundan emin olmak için açılmıyor, sonra utime'u arayalım?
itsadok

31

Neden denemiyorsunuz ?:

import os

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

Bunun önemli olan yarış koşullarını ortadan kaldırdığına inanıyorum. Dosya mevcut değilse, bir istisna atılır.

Burada mümkün olan tek yarış koşulu, dosya open () çağrılmadan önce ancak os.utime () öğesinden sonra oluşturulmuşsa oluşur. Ancak bu önemli değil çünkü bu durumda, dokunma () çağrısı sırasında olması gereken değişiklik süresi beklendiği gibi olacaktır.


8

İşte ctypes kullanan bazı kodlar (sadece Linux'ta test edilmiştir):

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

Bu yanıt, anahtar kelime withserbest bırakıldığında Python-2.5'ten beri tüm sürümlerle uyumludur .

1. Varsa dosya oluştur + Geçerli saati ayarla
(komutla tamamen aynı 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

Daha sağlam bir sürüm:

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. Sadece yoksa dosyayı oluşturun
(zamanı güncellemez)

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

3. Sadece dosya erişimini / değiştirilen süreleri güncelleyin
(mevcut değilse dosya oluşturmaz)

import os

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

Kullanmak os.path.exists()kodu basitleştirmez:

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: Bir dizindeki tüm dosyaların süresini güncelleme

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)

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

Başarısız : with open(fn,'a'): passveya alternatif open(fn, 'a').close(), Red Hat 7'de Python 2.7.5 kullanarak değiştirilen zamanı değiştirmeyin (dosya sistemi XFS'dir). Platformumda, bu çözümler yoksa boş bir dosya oluşturur. : - /
olibre

3

Basit:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • openOlmasını sağlar bir dosya var orada
  • utimedamgaları güncellenir olmasını sağlar

Teorik olarak, birinin dosyayı silmesinin openbir istisna yaratmasına neden olması mümkündür. Ama muhtemelen sorun değil, çünkü kötü bir şey oldu.


1

Karmaşık (muhtemelen 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)

Bu aynı zamanda GNU dokunma gibi erişim veya değiştirme süresinin ayarlanmasına da izin vermeye çalışır.


1

İstenen değişkenlere sahip bir dize oluşturmak ve os.system'a aktarmak mantıklı görünebilir:

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

Bu, çeşitli şekillerde yetersizdir (örneğin, boşlukla başa çıkmaz), bu yüzden yapmayın.

Daha sağlam bir yöntem, alt süreci kullanmaktır:

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

Bu bir alt kabuk (os.system ile) kullanmaktan çok daha iyi olsa da, yine de sadece hızlı ve kirli komut dosyaları için uygundur; platformlar arası programlar için kabul edilen cevabı kullanın.


Bu çok güvenli değil: dosya adında bir boşluk olduğunda ne olur?
ayke

5
subprocess.call(['touch', os.path.join(dirname, fileName)])(ile os.system) bir alt kabuk kullanmaktan çok daha iyidir . Ama yine de, bunu sadece hızlı ve kirli komut dosyaları için kullanın, platformlar arası programlar için kabul edilen cevabı kullanın.
ayke

1
touchplatformlar arası kullanılabilir bir komut değildir (örn. Windows)
Mike T

1

"open (dosya_adı, 'a'). close ()" Windows'taki Python 2.7'de çalışmadı. "os.utime (dosya_adı, Hiçbiri)" düzgün çalıştı.

Ayrıca, bir tarihten daha eski bir tarihe sahip bir dizindeki tüm dosyalara tekrar tekrar dokunmam gerekiyordu. Ephemient'in çok yardımcı tepkisine dayanarak hte takip ettim.

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

Neden denemiyorsunuz: newfile.py

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

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

python newfile.py foobar.txt

veya

alt süreci kullan:

import subprocess
subprocess.call(["touch", "barfoo.txt"])

0

Aşağıdakiler yeterlidir:

import os
def func(filename):
    if os.path.exists(filename):
        os.utime(filename)
    else:
        with open(filename,'a') as f:
            pass

Dokunma için belirli bir zaman ayarlamak istiyorsanız, os.utime komutunu aşağıdaki gibi kullanın:

os.utime(filename,(atime,mtime))

Burada, hem atime hem de mtime int / float olmalı ve ayarlamak istediğiniz zamana kadar saniye cinsinden zamana eşit olmalıdır.


0

Deneyin dışında sakıncası yoksa ...

def touch_dir(folder_path):
    try:
        os.mkdir(folder_path)
    except FileExistsError:
        pass

Yine de dikkat edilmesi gereken bir şey, eğer aynı adda bir dosya varsa o zaman işe yaramaz ve sessizce başarısız olur.


0

write_text()den pathlib.Pathkullanılabilir.

>>> from pathlib import Path
>>> Path('aa.txt').write_text("")
0
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.