बैश की सशर्त अभिव्यक्तियों में -a और -e का क्या अंतर है?


12

से man bash:

CONDITIONAL EXPRESSIONS
[...]
       -a file
              True if file exists.
[...]
       -e file
              True if file exists.
  1. तो क्या [ -a $FILE ]और [ -e $FILE ]अगर, के बीच अंतर है ?
  2. यदि कोई वास्तविक अंतर नहीं है, तो एक ही उद्देश्य के लिए दो झंडे क्यों मौजूद हैं?

जब तक वे समुदाय को अपना तर्क साझा नहीं करते, केवल डेवलपर्स को # 2 --- पता होगा।
बेलमिन फर्नांडीज

जवाबों:


13

में bash, दो तर्क के संदर्भ के साथ testकमान, -a fileऔर -e fileएक ही हैं। लेकिन उनके पास कुछ अंतर है, क्योंकि -aएक बाइनरी ऑपरेटर भी है।

-eयूनिरी को पोसिक्स द्वारा परिभाषित किया गया है, लेकिन -aयूनरी नहीं है। POSIX केवल -aबाइनरी को परिभाषित करता है ( परीक्षण POSIX देखें )।

POSIX तीन तर्क testव्यवहार को परिभाषित करता है:

3 तर्क:

  • यदि $ 2 एक बाइनरी प्राइमरी है, तो $ 1 और $ 3 का बाइनरी टेस्ट करें।

  • यदि $ 1 '' है, तो $ 2 और $ 3 के दो-तर्क परीक्षण को नकारें।

  • यदि $ 1 '(' और $ 3 'है') है, तो $ 2 का एकात्मक परीक्षण करें। उन प्रणालियों पर जो XSI विकल्प का समर्थन नहीं करते हैं, यदि $ 1 '(' और $ 3 '') है तो परिणाम अनिर्दिष्ट हैं।

  • अन्यथा, अनिर्दिष्ट परिणामों का उत्पादन करें।

इसलिए -aभी अजीब परिणाम होता है:

$ [ ! -a . ] && echo true
true

-aतीन तर्कों के संदर्भ में बाइनरी ऑपरेटर के रूप में माना जाता है। बैश FAQ प्रश्न E1 देखें । POSIX में -aकॉर्नशेल से प्राप्त होने का भी उल्लेख है लेकिन बाद में -eइसे बदल दिया गया क्योंकि यह -aबाइनरी और अनरी के बीच भ्रामक बनाता है -a

-ई प्राइमरी, जिसमें सी शेल द्वारा प्रदान की गई समान कार्यक्षमता है, को जोड़ा गया क्योंकि यह शेल स्क्रिप्ट के लिए एकमात्र तरीका प्रदान करता है ताकि यह पता लगाया जा सके कि फ़ाइल खोलने की कोशिश किए बिना कोई फ़ाइल मौजूद है या नहीं। चूंकि कार्यान्वयन को अतिरिक्त फ़ाइल प्रकारों को जोड़ने की अनुमति है, एक पोर्टेबल स्क्रिप्ट का उपयोग नहीं किया जा सकता है:

test -b foo -o -c foo -o -d foo -o -f foo -o -p foo

पता लगाने के लिए कि क्या फू एक मौजूदा फ़ाइल है। ऐतिहासिक बीएसडी प्रणालियों पर, एक फ़ाइल का अस्तित्व निम्न द्वारा निर्धारित किया जा सकता है:

test -f foo -o -d foo

लेकिन यह निर्धारित करने का कोई आसान तरीका नहीं था कि एक मौजूदा फ़ाइल एक नियमित फ़ाइल थी। एक प्रारंभिक प्रस्ताव में कोर्नशेल-ए प्राथमिक (समान अर्थ के साथ) का उपयोग किया गया था, लेकिन इसे -ई में बदल दिया गया था क्योंकि मानव बाइनरी ऑपरेटर के साथ -a प्राथमिक को भ्रमित करने वाले मनुष्यों की उच्च संभावना के बारे में चिंताएं थीं।

-aबाइनरी को भी अप्रचलित के रूप में चिह्नित किया गया है, क्योंकि यह कुछ अस्पष्ट अभिव्यक्ति की ओर जाता है, जिसमें 4 से अधिक तर्क हैं। इन> 4 तर्कों की अभिव्यक्ति के साथ, POSIX परिभाषित करता है कि परिणाम अनिर्दिष्ट है।


जानने के लिए अच्छा है! अब यह थोड़ा और स्पष्ट है :)!
पॉलीम जूल

9

.1। तो [-a $ FILE] और [-E $ FILE] में अंतर है, यदि कोई हो तो?

कोई फर्क नहीं है।

बैश संस्करण में लाइन 505-507में :test.c4.2.45(1)-release

case 'a':           /* file exists in the file system? */
case 'e':
  return (sh_stat (arg, &stat_buf) == 0);

यह इंगित करता है कि दोनों झंडे के बीच कोई वास्तविक अंतर नहीं है।

.2। यदि कोई वास्तविक अंतर नहीं है, तो एक ही उद्देश्य के लिए दो झंडे क्यों मौजूद हैं?

देखें gnouc का जवाब।


3
दूसरी ओर, यह देखते हुए कि पर -aहै भी एक बूलियन ऑपरेटर (और) बैश में, यह बग इस अतिरिक्त अर्थ है कि पूरी तरह से बेमानी है जोड़ने के होने का खतरा लगता है, मुझे लगता है कि यह कुछ अन्य कार्यान्वयन और / या पहले के संस्करणों के साथ संगतता से संबंधित है जो नहीं था -e
celtschk

@celtschk - यह बगप्रॉन नहीं है, लेकिन शेल का पार्सर हो सकता है। POSIX के लिए -aऔर -oबूलियन निर्दिष्ट करता है [ test ]। लेकिन कुछ गोले (जैसे bash) एक ऑपरेटर से एक तर्क को अलग करने पर चूसे और [ test ]परिणाम अविश्वसनीय थे। तब से POSIX के लिए आवश्यक है कि कोई भी कंप्लेंट शेल [ test ]ब्रैकेट के भीतर कम से कम 4 तर्कों को हैंडल करे ।
mikeserv

5

सबसे अच्छा जवाब जो मुझे मिला है वह एक है, स्टैकऑवरफ्लो प्रश्न से:

-aपदावनत किया जाता है, इस प्रकार /usr/bin/testअब के लिए मेन्यू में सूचीबद्ध नहीं है, लेकिन अभी भी बैश के लिए एक में है। का उपयोग करें -e। सिंगल '[' 'के लिए, testबैश बिलिन, बैश बिलिन के समान व्यवहार करता है, जो उसी के समान व्यवहार करता है /usr/bin/[और /usr/bin/test (एक दूसरे के लिए एक सहिष्णु होता है)। -aइसकी स्थिति पर निर्भर करता है के प्रभाव पर ध्यान दें : यदि यह शुरुआत में है, तो इसका मतलब है file exists। यदि यह दो भावों के मध्य में है, तो इसका अर्थ तार्किक है and

[ ! -a /path ] && echo existsकाम नहीं करता है, क्योंकि बाश मैनुअल बताता है कि -aवहाँ एक द्विआधारी ऑपरेटर माना जाता है, और इसलिए ऊपर negate -a ..एक if '!' and '/path' is true(गैर-खाली) के रूप में पार्स नहीं किया गया है । इस प्रकार, आपकी स्क्रिप्ट हमेशा आउटपुट "-a"(जो वास्तव में फाइलों के लिए परीक्षण करती है), और "! -a"जो वास्तव में andयहां एक बाइनरी है।

के लिए [[, अब -aएक बाइनरी के रूप में उपयोग नहीं किया जाता है and( &&वहां उपयोग किया जाता है), इसलिए इसका अनूठा उद्देश्य वहां एक फ़ाइल की जांच करना है (हालांकि पदावनत किया जा रहा है)। इसलिए, नकारात्मकता वास्तव में वही करती है जो आप उम्मीद करते हैं।

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