2008-11-26 9 views
34

दोनों के बारे में "एक" और बैश दस्तावेज में "-e" विकल्प (http://www.gnu.org/software/bash/manual/bashref.html#Bash-Conditional-Expressions) बनाम कहा गया है:बैश अगर -एक -e विकल्प

-a file 
    True if file exists. 
-e file 
    True if file exists. 

क्या अंतर है पाने के लिए कोशिश कर रहा है मैं निम्नलिखित भाग गया स्क्रिप्ट:

resin_dir=/Test/Resin_wheleph/Results 

if [ -e ${resin_dir} ] ; then 
    echo "-e "; 
fi 

if [ ! -e ${resin_dir} ] ; then 
    echo "! -e"; 
fi 

if [ -a ${resin_dir} ] ; then 
    echo "-a"; 
fi 

if [ ! -a ${resin_dir} ] ; then 
    echo "! -a"; 
fi 

/टेस्ट/Resin_wheleph/परिणाम मौजूद हैं और एक निर्देशिका है। और यह मैं क्या मिलता है:

-e 
-a 
! -a 

जो एक छोटे से अजीब है (ध्यान दें "एक" और "-एक!") हो रहा है।

-e 
-a 

तो:

  1. के बीच "एक" और "-e" विकल्प एक अंतर क्या है लेकिन जब मैं इसी तरह की स्क्रिप्ट में उपयोग डबल कोष्ठक (।। ई जी if [[ -e ${resin_dir} ]]) यह उचित उत्पादन देता है?
  2. क्यों "-a" एक अजीब परिणाम उत्पन्न करता है जब एकल ब्रैकेट के अंदर उपयोग किया जाता है?
+0

यकीन नहीं है कि क्या मैनपेज सही है "आदमी परीक्षण" का कहना है कि यह है "और" –

उत्तर

48

मैं शोध किया है, और यह काफी बालों है:

-a हटाई गई है, इस प्रकार /usr/bin/test के लिए मैनपेज में अब और सूचीबद्ध नहीं है, लेकिन अभी भी पार्टी के लिए एक में। -e का प्रयोग करें। एकल के लिए '[', बैश builtin 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 अब के रूप में है, इसलिए इसकी अद्वितीय उद्देश्य वहाँ एक फ़ाइल के लिए जाँच करने के लिए (हालांकि समाप्त किया जा रहा है) नहीं किया जाता है (&& वहाँ प्रयोग किया जाता है)। तो, वास्तव में अस्वीकृति जो आप उम्मीद करते हैं।

+0

बैश निर्मित एकल मोड और -एक में -e रूप -एक का उपयोग करता है के रूप में और द्विआधारी मोड में। [[]] का उपयोग करके निर्मित []] का उपयोग किया जाता है, यही कारण है कि आपको इसके साथ उचित आउटपुट क्यों मिला। एकल [ब्रैकेट ने परीक्षण बाइनरी का उल्लेख किया है जो यूनरी स्वीकार करता है लेकिन इसका सही इलाज नहीं करता है (बाइनरी के रूप में उपयोग किया जाना चाहिए) – flolo

+1

बहुत कम गोले वास्तव में आह्वान/बी इन/टेस्ट (या/bin/[) जब आप 'if [...]' लिखते हैं। एक बार बहुत समय पहले - हाँ; आजकल, नहीं। वेनिला बोर्न शेल भी नहीं। –

+0

हाँ मुझे लगता है कि शैल बिल्टिन हमेशा प्राथमिकता लेते हैं –

0

डबल ब्रैकेट [[exp]] एक बैश builtin है। बैश-ए और-ए में समान रूप से कुछ पिछड़ा संगतता के लिए समान हैं।

एकल ब्रैकेट [exp] बाहरी कमांड "परीक्षण" के लिए उपनाम है। "परीक्षण" में, -एक तार्किक है और। हालांकि [कुछ भी नहीं और $ STRING] लगता है कि यह गलत हो सकता है, परीक्षण कुछ वाक्य रचना quirks है, जिसके कारण मैं बैश builtin [[exp]], जो जाता है और अधिक समझदार होने के लिए उपयोग करने की अनुशंसा की है।

नोट: बैश वास्तव में जब आप का उपयोग करें "[" कॉल/bin/[करता है।

$ [ $UNASIGNED_VAR == "bar" ] 
bash: [: ==: unary operator expected 

त्रुटि दिखाता है बैश कहा जाता है [। एक strace भी पता चलता "execve ("/usr/bin/[ "..."

+0

[जेएस @ HOST2 cpp] $ alias foo bash: alias: foo: नहीं मिला [जेएस @ HOST2 cpp] $ क्या इसका मतलब उपनाम है एक बाहरी आदेश है? नहीं, यह अभी भी एक बिल्टिन है :) –

+0

डर्न, अच्छा एक :)। फिर भी, एक बैश स्क्रिप्ट को स्ट्र्रेस करने से पता चलता है "निष्पादित करें ("/usr/bin/[", ... – JimB

+0

दिलचस्प: सोलारिस पर, मेरे जवाब में 'truss -o bash.truss bash ...' का उपयोग करके और फिर 'grep -n exec bash.truss' का उपयोग करके केवल पंक्ति 1 को बाश को निष्पादित करता है। इसलिए यह अजीब है। (एक/usr/bin/[Solaris पर भी नहीं है - एक/usr/bin/test है।) –

3

'-a' परीक्षण ऑपरेटर के लिए विकल्प के लिए एक एकल ऑपरेटर और एक अन्य एक द्विआधारी ऑपरेटर के रूप में के रूप में एक अर्थ नहीं है। एक द्विआधारी ऑपरेटर के रूप में, यह 'और' संयोजी (और '-o' है 'या' । संयोजी) एक एकल ऑपरेटर के रूप में, यह जाहिरा तौर पर एक फ़ाइल के अस्तित्व के लिए परीक्षण

autoconf प्रणाली आप को सलाह देता है '-a' का उपयोग कर से बचने के लिए, क्योंकि यह भ्रम का कारण बनता;। अब मैं देख रहा हूँ क्यों दरअसल, पोर्टेबल खोल प्रोग्रामिंग में, यह है। && 'या' || 'के साथ शर्तों को गठबंधन करने के लिए सबसे अच्छा।

मुझे लगता है कि @litb दाईं ओर है धावन पथ। जब आपके पास '! -a ${resin_dir}' है, तो बैश इसे "स्ट्रिंग है" के रूप में व्याख्या कर सकता है! गैर-खाली और '$ {resin_dir}' में स्ट्रिंग गैर-खाली है, जिसके लिए उत्तर हाँ है। कॉर्न शैल इस पर एक अलग दृश्य है, और बोर्न शैल अभी तक एक और दृश्य है - इसलिए '-a' से दूर रहें ।

Solaris 10 पर:।

$ bash -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
Bad 
$ ksh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
OK 
$ sh -c 'x=""; if [ ! -a "$x" ] ; then echo OK ; else echo Bad; fi' 
sh: test: argument expected 
$