पायथन का उपयोग करके स्पर्श को लागू करें?


352

touchयूनिक्स उपयोगिता है जो दिन के वर्तमान समय में फाइलों के संशोधन और पहुंच समय को निर्धारित करती है। यदि फ़ाइल मौजूद नहीं है, तो इसे डिफ़ॉल्ट अनुमतियों के साथ बनाया गया है।

आप इसे पायथन फ़ंक्शन के रूप में कैसे लागू करेंगे? पार मंच और पूरा होने की कोशिश करो।

("अजगर स्पर्श फ़ाइल" के लिए वर्तमान Google परिणाम बहुत बढ़िया नहीं हैं, लेकिन os.utime को इंगित करते हैं ।)


4
कृपया स्वीकार किए गए उत्तर को अपडेट करने पर विचार करें कि यह कार्यक्षमता पायथन stdlib में बनाई गई है।
मील

@ मीलों का स्वीकृत उत्तर वही करता है जो सवाल पूछा गया था - यह वास्तव में एक पुस्तकालय का उपयोग करने के बजाय पायथन में फ़ंक्शन को लागू करता है।
स्टायरोफोम ने

5
@styrofoamfly मानक पुस्तकालय पायथन का हिस्सा है। यह वास्तव में संभावना है कि प्रश्न पूछने वाला वास्तव में जानना चाहता है (और Google के माध्यम से इस सवाल पर पहुंचने वाले अधिकांश लोग) touchअपने पायथन कार्यक्रमों में कार्यक्षमता को कैसे प्राप्त करना है, न कि इसे खरोंच से कैसे फिर से लागू करना है; उन लोगों को pathlibसमाधान के लिए नीचे स्क्रॉल करके सबसे अच्छा काम किया जाता है । भले ही यह अब बिल्ट-इन है, लेकिन प्रासंगिक प्रलेखन की तुलना में इस उत्तर में "पायथन टच फाइल" के लिए बेहतर रैंकिंग है ।
माइल

@ मील्स पायथन 2 (दुर्भाग्य से) अभी भी 3 से अधिक व्यापक रूप से उपयोग किया जाता है, इसलिए मुझे लगता है कि स्वीकृत उत्तर अभी भी अधिक प्रासंगिक है। लेकिन आपकी टिप्पणी दूसरे उत्तर के लिए लोगों को इंगित करने का अच्छा काम करती है।
इसकायादोक

6
इस वर्ष के अंत में पायथन 2 ईओएल है।
मैक्स गैसनर

जवाबों:


304

ऐसा लगता है कि पायथन 3.4 के रूप में यह नया है - pathlib

from pathlib import Path

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

इससे file.txtमार्ग पर निर्माण होगा ।

-

Path.touch (मोड = 0o777, अस्तित्व_ोक = सत्य)

इस दिए गए पथ पर एक फ़ाइल बनाएँ। यदि मोड दिया जाता है, तो यह फ़ाइल मोड और एक्सेस फ़्लैग को निर्धारित करने के लिए प्रक्रिया के umask मूल्य के साथ संयुक्त है। यदि फ़ाइल पहले से मौजूद है, तो फ़ंक्शन सफल होता है यदि अस्तित्व_ सही है (और इसका संशोधन समय वर्तमान समय में अपडेट किया गया है), अन्यथा FileExistsError उठाया जाता है।


3
पायथन2.7 पर:pip install pathlib
आंद्रे

8
स्वयं पर ध्यान दें: Path('/some/path').mkdir()यदि touch()एड होने वाली फ़ाइल में निर्देशिका मौजूद नहीं है, तो उसका उपयोग करें ।
जैकबिर

1
मुझे लगता है कि हमें pathlib2इसके बजाय उपयोग करना चाहिए pathlibक्योंकि pathlibबगफिक्स-केवल अब है। इसलिए, पायथन 2.7 पर: pip install pathlib2और फिर from pathlib2 import Path
इयान लिन

@ इनलिन कुछ ऐसा करने के लिए एक पुस्तकालय स्थापित करने का बहुत कम कारण है जो मानक पुस्तकालय पहले से ही समर्थन करता है। क्या आप bitbucket.org/pitrou/pathlib/src/default को docs.python.org/dev/library/pathlib.html से भ्रमित कर रहे हैं ?
माइकल Mrozek

वह टिप्पणी आंद्रे की उस टिप्पणी का जवाब दे रही है जो पायथन 2.7 के बारे में बता रही है, जिसमें वह मानक पुस्तकालय नहीं है। दस्तावेज़ को pypi.org/project/pathlib2
इयान लिन

242

यह अन्य समाधानों की तुलना में थोड़ी अधिक दौड़-मुक्त होने की कोशिश करता है। ( withपायथन 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माध्यम से ctypesया इसी तरह के बिना जाने के लिए एक रास्ता प्रदान करने के लिए प्रतीत नहीं होता है ...


संपादित करें

द्वारा बताया गया है नैट पार्सन्स , अजगर 3.3 जाएगा जोड़ने के एक फ़ाइल वर्णनकर्ता को निर्दिष्ट (जब os.supports_fd) जैसे कार्यों के लिए os.utimeजो प्रयोग करेंगे, futimesके बजाय syscall utimesहुड के नीचे syscall। दूसरे शब्दों में:

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)

यह वास्तविक समाधान है - और यह है कि जब तक वायदा () उपलब्ध नहीं होता है, तो कोर्यूटिल में स्पर्श (1) करता है। वायदा एक पोर्टेबल फ़ंक्शन नहीं है और पुराने 2.6 लिनक्स कर्नेल पर भी मौजूद नहीं है, इसलिए आपको ENOSYS से निपटने और उपयोग करने पर भी वापस गिरने की आवश्यकता है।
ग्लेन मेनार्ड

(उपरोक्त त्रुटि: "यह" = खुला ("a") + भविष्य।) सौभाग्य से, यह एक ऐसे मामले के बारे में सोचना मुश्किल है जहां वास्तव में उपयोग नहीं होने वाले दौड़ की स्थिति की स्थिति मायने रखती है। आपके द्वारा समाप्त किया जा सकता "गलत" मामला वह फ़ाइल है जिसे खुले () और utime () के बीच में बदला जा रहा है, जिस स्थिति में आप न तो नई फ़ाइल बनाएंगे और न ही पुराने को स्पर्श करेंगे। यह बात हो सकती है, लेकिन अधिकांश समय ऐसा नहीं होगा।
ग्लेन मेनार्ड

साइबरविन टच अपना जादू केवल-पढ़ने वाली फ़ाइलों पर कर सकता है, लेकिन यह कोड नहीं कर सकता। हालांकि यह काम करने के लिए लगता है अगर मैं इसे कोशिश के साथ घेरता हूं: <code> IOError को e के रूप में छोड़कर: (check e.errno) os.utime (फ़ाइल नाम, समय)
डैश-टॉम-बैंग

FYI करें, ऐसा लगता है जैसे 3.3 में जोड़ा गया था
Nate Parsons

नोट: अंतर्निहित fileफ़ंक्शन पायथन 3 से हटा दिया गया था, और openइसके बजाय इसका उपयोग किया जाना है। मैं इसे पूरी तरह से याद कर रहा था, क्योंकि मैं जिस संपादक (gedit) का उपयोग कर रहा हूं उसका वाक्यविन्यास हाइलाइटिंग अभी भी पायथन 2 को लक्षित कर रहा है
बार्ट

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

24
इस समाधान में एक संभावित दौड़ की स्थिति है: यदि फ़ाइल मौजूद नहीं है, और इस फ़ंक्शन को open()कॉल पर पहुंचने से पहले किसी अन्य प्रक्रिया द्वारा बनाई गई है , तो फ़ाइल की सामग्री को छोटा कर दिया जाएगा। 'a'इसके बजाय मोड का उपयोग करने का सुझाव दें।
ग्रेग हेवगिल

7
माना। उचित समाधान सिर्फ है: def टच (fname): ओपन (fname, 'wa')।
Close

@Greg, जबकि यह संभावित रेसिंग स्थिति समस्या को हल करता है, open(fname, 'a').close()atime नहीं बदलेगा।
SilentGhost

@SilentGhost: यह सच है, लेकिन यह ठीक है क्योंकि यदि फ़ाइल मौजूद है तो इसे अभी बनाया गया था । बेशक आप os.utime()पहले से मौजूद फ़ाइलों के लिए कॉल को वहीं छोड़ देंगे ।
ग्रेग हेवगिल

4
केवल यह सुनिश्चित करने के लिए खुला क्यों नहीं कि यह मौजूद है, फिर कॉल करें?
इसकी जद

31

यह कोशिश क्यों नहीं ?:

import os

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

मेरा मानना ​​है कि यह किसी भी दौड़ की स्थिति को समाप्त करता है जो मायने रखता है। यदि फ़ाइल मौजूद नहीं है, तो एक अपवाद फेंक दिया जाएगा।

यहां केवल संभव दौड़ की स्थिति है अगर फ़ाइल को खोलने से पहले बनाया जाता है () कहा जाता है, लेकिन os.utime () के बाद। लेकिन इससे कोई फर्क नहीं पड़ता क्योंकि इस मामले में संशोधन समय अपेक्षित होगा क्योंकि यह कॉल टू टच () के दौरान हुआ होगा।


8

यहां कुछ कोड हैं जो ctypes का उपयोग करते हैं (केवल लिनक्स पर परीक्षण किया गया है):

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

यह उत्तर पायथन -2.5 के बाद से सभी संस्करणों के साथ संगत है जब कीवर्ड 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() 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)

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

विफल : with open(fn,'a'): passया विकल्प open(fn, 'a').close()Red Hat 7 (फाइलसिस्टम XFS है) पर पायथन 2.7.5 का उपयोग कर संशोधित समय को न बदलें। मेरे मंच पर, ये समाधान केवल एक खाली फ़ाइल बनाते हैं यदि मौजूद नहीं है। : - /
ओलिब्रे

3

सरलीकृत:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • यह openसुनिश्चित करता है कि वहां एक फाइल हो
  • यह utimeसुनिश्चित करता है कि टाइमस्टैम्प अपडेट किए गए हैं

सैद्धांतिक रूप से, यह संभव है कि कोई व्यक्ति फ़ाइल को हटा देगा open, जिसके कारण एक अपवाद बढ़ाने के लिए utime। लेकिन यकीनन यह ठीक है, क्योंकि कुछ बुरा हुआ था।


1

जटिल (संभवतः छोटी गाड़ी):

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 टच जैसे एक्सेस या संशोधन समय को सेट करने की भी अनुमति देता है।


1

यह वांछित चर के साथ एक स्ट्रिंग बनाने के लिए तर्कसंगत लग सकता है, और इसे os.system में पास कर सकता है:

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

यह कई तरीकों से अपर्याप्त है (उदाहरण के लिए, यह व्हाट्सएप को नहीं संभालता है), इसलिए ऐसा न करें।

एक और अधिक मजबूत विधि उपप्रकार का उपयोग करना है:

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

हालांकि यह सबस्क्रिप्शन (os.system के साथ) का उपयोग करने की तुलना में बहुत बेहतर है, यह अभी भी त्वरित और गंदे लिपियों के लिए उपयुक्त है; क्रॉस-प्लेटफ़ॉर्म कार्यक्रमों के लिए स्वीकृत उत्तर का उपयोग करें।


यह बहुत सुरक्षित नहीं है: क्या होता है जब फ़ाइल नाम में कोई स्थान होता है?
एक्यू जूल

5
subprocess.call(['touch', os.path.join(dirname, fileName)])एक उपखंड (के साथ os.system) का उपयोग करने से बेहतर है । लेकिन फिर भी, केवल त्वरित और गंदी स्क्रिप्ट के लिए इसका उपयोग करें, क्रॉस-प्लेटफ़ॉर्म कार्यक्रमों के लिए स्वीकृत उत्तर का उपयोग करें।
अयेक a

1
touchएक क्रॉस-प्लेटफ़ॉर्म उपलब्ध कमांड नहीं है (उदाहरण के लिए विंडोज)
माइक टी

1

"ओपन (फ़ाइल_नाम, 'ए')। क्लोज़ ()" मेरे लिए विंडोज पर पायथन 2.7 में काम नहीं किया। "os.utime (file_name, कोई नहीं)" बस ठीक काम किया।

इसके अलावा, मुझे एक निर्देशिका में सभी फाइलों को कुछ तारीख से पुरानी तारीख के साथ पुनरावृत्ति करने की आवश्यकता थी। मैंने एपिथिएंट की बहुत उपयोगी प्रतिक्रिया के आधार पर हेट का निर्माण किया।

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

आप प्रयास क्यों नहीं करते: 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"])

0

निम्नलिखित पर्याप्त है:

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

यदि आप स्पर्श के लिए एक विशिष्ट समय निर्धारित करना चाहते हैं, तो os.utime का उपयोग इस प्रकार करें:

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

यहां, एटिम और माइम दोनों इंट / फ्लोट होने चाहिए और सेकंड में उस समय के बराबर होना चाहिए, जिसे आप सेट करना चाहते हैं।


0

यदि आप कोशिश को छोड़कर मन नहीं है तो ...

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

एक बात पर ध्यान दें, यदि कोई फ़ाइल समान नाम के साथ मौजूद है तो वह काम नहीं करेगी और चुपचाप विफल हो जाएगी।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.