अगर गो में कोई फाइल मौजूद है तो कैसे जांच करें?


435

गो की मानक लाइब्रेरी में पूरी तरह से यह जाँचने का इरादा नहीं है कि कोई फाइल मौजूद है या नहीं (जैसे कि पायथन की os.path.exists)। इसे करने का मुहावरेदार तरीका क्या है?


मैं वास्तव में यह नहीं मिलता है। उसी मिनट में आप कहते हैं कि कोई मानक फ़ंक्शन नहीं है और आप मानक फ़ंक्शन के साथ उत्तर लिखते हैं। मैं क्या खो रहा हूँ ? कम से कम सवाल तय नहीं होना चाहिए?
डेनसिटी सेगुरेट

@ डिस्ट्रोय - सवाल तय किया।
श्रीधर रत्नाकुमार

11
बेहतर फ़ाइल अस्तित्व की पूछताछ से बचना चाहिए। उत्तर की दुर्लभ प्रकृति के बी / सी, प्राप्त जानकारी कहती है कि वास्तव में पूछे गए समय में मौजूद फ़ाइल के ऊपर कुछ भी उपयोगी नहीं है - लेकिन यह अब मौजूद नहीं हो सकता है। सिफारिश करने का तरीका बस एक फ़ाइल को खोलना और जांचना है कि क्या विफल रहता है या नहीं।
zzzz


2
@zzzz (मुझे पता है कि यह साल हो गया है, यह टिप्पणी नए पाठकों के लिए है) मैं सामान्य मामले में सहमत हूं। लेकिन मेरा ऐप एक थर्ड पार्टी लाइब्रेरी को लोड करता है जो इनिशियलाइज़ेशन डेटा के रूप में कुछ फ़ाइल पाथ लेता है लेकिन अगर फाइल मौजूद नहीं है तो सीगफॉल्ट्स। मुझे लगता है कि यह जाँचने के लिए एक वैध परिदृश्य है कि यदि फाइल मौजूद है, तो इसे खोलने की कोशिश कर रहा है कि यह एक घातक दुर्घटना के बिना त्रुटि की रिपोर्ट करने में सक्षम है, क्योंकि मेरे कोड को फ़ाइल सामग्री को पढ़ने या सीधे फ़ाइल में लिखने की आवश्यकता नहीं है।
सर्जियो अकोस्टा

जवाबों:


691

यह जाँचने के लिए कि क्या कोई फ़ाइल मौजूद नहीं है, पायथन के समकक्ष if not os.path.exists(filename):

if _, err := os.Stat("/path/to/whatever"); os.IsNotExist(err) {
  // path/to/whatever does not exist
}

यह जाँचने के लिए कि क्या कोई फ़ाइल मौजूद है, पायथन के समकक्ष if os.path.exists(filename):

संपादित: हाल की टिप्पणियों के अनुसार

if _, err := os.Stat("/path/to/whatever"); err == nil {
  // path/to/whatever exists

} else if os.IsNotExist(err) {
  // path/to/whatever does *not* exist

} else {
  // Schrodinger: file may or may not exist. See err for details.

  // Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence


}

3
कभी-कभी यह बदले में ENOTDIR लौटता है NOTEXIST, उदाहरण के लिए, यदि /etc/bashrcमौजूद है, तो /etc/bashrc/foobarवापस आ जाएगाENOTDIR
lidaobing

43
दूसरा स्निपेट अधिक सूक्ष्म रूप से गलत है; हालत होना चाहिए !os.IsNotExist(err)। यह संभव है कि फ़ाइल मौजूद है, लेकिन os.Statअन्य कारणों (जैसे अनुमति, विफल डिस्क) के लिए विफल रहता है। err == nilइस स्थिति का गलत तरीके से उपयोग करने से ऐसी विफलताएं "फ़ाइल मौजूद नहीं हैं" के रूप में वर्गीकृत होती हैं।
sqweek

9
यह जाँचने के लिए कि क्या कोई फाइल मौजूद है गलत है:
इरेट

1
विस्तार करना सुनिश्चित करें ~ या फिर यह गलत वापस आएगा ... stackoverflow.com/questions/17609732/…
Marcello de Sales

आप केस के आधार पर os.IsExist () का उपयोग कर सकते हैं, ऐसा करने पर दोहरा नकार करने के बजाय अधिक मुहावरेदार हो सकता है! Os.IsNotExistant ()
एरियल मोनाको

126

Caleb स्पेयर द्वारा उत्तर गोनट्स मेलिंग सूची में पोस्ट किया गया ।

[...] यह वास्तव में बहुत बार की जरूरत नहीं है और [...] os.Statउन मामलों के लिए काफी आसान है जहां इसकी आवश्यकता होती है।

[...] उदाहरण के लिए: यदि आप फ़ाइल खोलने जा रहे हैं, तो यह जाँचने का कोई कारण नहीं है कि यह पहले मौजूद है या नहीं। फ़ाइल जाँचने और खोलने के बीच गायब हो सकती है, और वैसे भी आपको os.Openत्रुटि की जाँच करने की आवश्यकता होगी । इसलिए आप os.IsNotExist(err)फ़ाइल को खोलने का प्रयास करने के बाद बस कॉल करते हैं, और वहां उसके गैर-अस्तित्व से निपटते हैं (यदि इसके लिए विशेष हैंडलिंग की आवश्यकता होती है)।

[...] आपको उन रास्तों के लिए जाँच करने की आवश्यकता नहीं है जो (और आपको नहीं करना चाहिए)।

  • os.MkdirAllकाम करता है या नहीं पथ पहले से मौजूद हैं। (इसके अलावा आपको उस कॉल से त्रुटि की जांच करने की आवश्यकता है)

  • उपयोग करने के बजाय os.Create, आपको उपयोग करना चाहिए os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)। यदि फ़ाइल पहले से मौजूद है, तो आपको एक त्रुटि मिलेगी। इसके अलावा आपके पास अपने संस्करण के विपरीत फ़ाइल बनाने के साथ एक दौड़ की स्थिति नहीं है, जो पहले से मौजूद है।

इससे लिया गया: https://groups.google.com/forum/#-msg/golang-nuts/Ayx-BMNdMFo/4rL8FFHr8v4J


30

आपको निम्नलिखित उदाहरण के रूप में कार्यों os.Stat()और os.IsNotExist()कार्यों का उपयोग करना चाहिए :

// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
    if _, err := os.Stat(name); err != nil {
        if os.IsNotExist(err) {
            return false
        }
    }
    return true
}

उदाहरण यहाँ से निकाला गया है


12
खबरदार: जैसा कि stackoverflow.com/a/22467409/712014 ने बताया, यह कोड सही है, भले ही फ़ाइल मौजूद न हो, उदाहरण के लिए जब स्टेट () रिटर्न की अनुमति से इनकार करता है।
माइकल

19

User11617 द्वारा उदाहरण गलत है; यह रिपोर्ट करेगा कि फ़ाइल उन मामलों में भी मौजूद है जहां यह नहीं है, लेकिन किसी अन्य प्रकार की त्रुटि थी।

हस्ताक्षर एक्ज़िस्ट (स्ट्रिंग) (बूल, त्रुटि) होना चाहिए। और फिर, जैसा कि होता है, कॉल साइट्स बेहतर नहीं हैं।

उन्होंने जो कोड लिखा वह बेहतर होगा:

func Exists(name string) bool {
    _, err := os.Stat(name)
    return !os.IsNotExist(err)
}

लेकिन मैं इसके बजाय यह सुझाव देता हूं:

func Exists(name string) (bool, error) {
  _, err := os.Stat(name)
  if os.IsNotExist(err) {
    return false, nil
  }
  return err != nil, err
}

7
उदाहरण 5 क्या है? क्या आप विशिष्ट हो सकते हैं।
xlm

1
आपके दूसरे उदाहरण के लिए कई रिटर्न मानों को नष्ट करना होगा - जैसे _, इर: = os.Stat (नाम)
डेविड डंकन

6
क्यों बदले err != nilबदले err == nil? यदि कोई त्रुटि है, तो फ़ाइल शायद मौजूद नहीं है?
इडबरी

14

अन्य उत्तर क्या छूट गए, यह है कि फ़ंक्शन को दिया गया पथ वास्तव में एक निर्देशिका हो सकता है। निम्नलिखित फ़ंक्शन सुनिश्चित करता है, कि पथ वास्तव में एक फ़ाइल है।

func fileExists(filename string) bool {
    info, err := os.Stat(filename)
    if os.IsNotExist(err) {
        return false
    }
    return !info.IsDir()
}

इंगित करने के लिए एक और बात: यह कोड अभी भी एक दौड़ की स्थिति का कारण बन सकता है, जहां एक और धागा या प्रक्रिया निर्दिष्ट फ़ाइल को हटा देती है या बना देती है, जबकि fileExists फ़ंक्शन चल रहा है।

यदि आप इसके बारे में चिंतित हैं, तो अपने थ्रेड्स में एक लॉक का उपयोग करें, इस फ़ंक्शन तक पहुंच को अनुक्रमित करें या यदि एक से अधिक एप्लिकेशन शामिल हैं तो इंटर-प्रोसेस सेमाफोर का उपयोग करें। यदि अन्य एप्लिकेशन शामिल हैं, तो आपके नियंत्रण से बाहर, आप भाग्य से बाहर हैं, मुझे लगता है।


12
    _, err := os.Stat(file)
    if err == nil {
        log.Printf("file %s exists", file)
    } else if os.IsNotExist(err) {
        log.Printf("file %s not exists", file)
    } else {
        log.Printf("file %s stat error: %v", file, err)
    }


6

आइए पहले कुछ पहलुओं पर गौर करें, osपैकेज के द्वारा प्रदान किए गए दोनों फ़ंक्शन golangउपयोगिताओं नहीं हैं, लेकिन त्रुटि चेकर्स, मेरा क्या मतलब है कि वे क्रॉस प्लेटफॉर्म पर त्रुटियों को संभालने के लिए सिर्फ एक आवरण हैं।

तो मूल रूप से अगर os.Statयह फ़ंक्शन कोई त्रुटि नहीं देता है, तो इसका मतलब है कि फ़ाइल मौजूद है यदि आपको यह जाँचने की आवश्यकता है कि यह किस प्रकार की त्रुटि है, तो इन दो फ़ंक्शन का उपयोग आता है os.IsNotExistऔर os.IsExist

इसे Statफाइल थ्रोइंग एरर के रूप में समझा जा सकता है क्योंकि यह मौजूद नहीं है या यह एरर फेंक रहा है क्योंकि यह मौजूद है और इसके साथ कुछ समस्या है।

इन कार्यों को लेने वाला पैरामीटर प्रकार का होता है error, हालांकि आप nilइसे पारित करने में सक्षम हो सकते हैं, लेकिन यह समझ में नहीं आएगा।

यह इस तथ्य की ओर भी इशारा करता है कि IsExist is not same as !IsNotExist, वे दो अलग-अलग चीजें हैं।

तो अब अगर आप जानना चाहते हैं कि क्या किसी दिए गए फ़ाइल में मौजूद है, मैं सबसे अच्छा तरीका है पसंद करेंगे:

if _, err := os.Stat(path/to/file); !os.IsNotExist(err){
   //TODO
} 

1

जैसा कि अन्य उत्तरों में उल्लेख किया गया है, विभिन्न झंडों का उपयोग करने से आवश्यक व्यवहार / त्रुटियों का निर्माण करना संभव है os.OpenFile। वास्तव में, os.Createऐसा करने के लिए सिर्फ एक समझदार-चूक शॉर्टहैंड है:

// Create creates or truncates the named file. If the file already exists,
// it is truncated. If the file does not exist, it is created with mode 0666
// (before umask). If successful, methods on the returned File can
// be used for I/O; the associated file descriptor has mode O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*File, error) {
    return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

आप जिस व्यवहार में रुचि रखते हैं उसे प्राप्त करने के लिए आपको इन झंडों को खुद से जोड़ना चाहिए:

// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (
    // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
    O_RDONLY int = syscall.O_RDONLY // open the file read-only.
    O_WRONLY int = syscall.O_WRONLY // open the file write-only.
    O_RDWR   int = syscall.O_RDWR   // open the file read-write.
    // The remaining values may be or'ed in to control behavior.
    O_APPEND int = syscall.O_APPEND // append data to the file when writing.
    O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
    O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
    O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
    O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
)

आप जो चुनते हैं, उसके आधार पर आपको अलग-अलग त्रुटियां मिलेंगी।

यहां एक उदाहरण है जहां मैं लिखने के लिए एक फ़ाइल खोलना चाहता हूं, लेकिन मैं केवल एक मौजूदा फ़ाइल को काट दूंगा यदि उपयोगकर्ता ने कहा है कि ठीक है:

var f *os.File
if truncateWhenExists {
    // O_TRUNC - truncate regular writable file when opened.
    if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
        log.Fatalln("failed to force-open file, err:", err)
    }
} else {
    // O_EXCL - used with O_CREATE, file must not exist
    if f, err = os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644); err != nil {
        log.Fatalln("failed to open file, err:", err) 
   }
}

0

फ़ाइल मौजूद है या नहीं यह जांचने का सबसे अच्छा तरीका:

if _, err := os.Stat("/path/to/file"); err == nil || os.IsExist(err) {
    // your code here if file exists
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.