क्यों जाँचता है कि क्या एक फ़ोल्डर मौजूद है -d एक रिक्त स्ट्रिंग रिटर्न सही पर?


8

मैं कुछ स्क्रिप्ट लिख रहा था और कुछ ऐसा लिख ​​रहा था

ARTIFACTS="/SOME/PATH"
[ -d $ARTIFCATS ] && rm -rf $ARTIFACTS/*

क्या हुआ कि मूर्खता से बाहर मैंने पहली निष्पादित किए बिना दूसरी पंक्ति को निष्पादित किया। यह पता चला कि [-d ""] सही है और अभिव्यक्ति बन गई

rm -rf /*

सौभाग्य से यह केवल एक परीक्षण मशीन थी और मैं एक सुडोल नहीं था, लेकिन हालांकि मैंने कुछ डेटा खो दिया

मेरा सवाल है, क्यों [-d ""] सच लौटाओ ?? प्रलेखन स्पष्ट रूप से बताता है कि क्या पथ मौजूद है और एक फ़ोल्डर है

मैंने उपयोग करके समस्या हल की

[ -e $ARTIFACTS ]
जो काम करने लगता है

चियर्स


5
या हो सकता है कि आपने दोनों लाइनों को निष्पादित किया हो। ऊपर दिए गए कोड उदाहरण में, आपने कभी ARTIFCATS सेट नहीं किया है।
बुहब

2
मैं बस के रूप में लिखा होगा कि rm -rf $ARTIFACTSबिना/* । यह $ARTIFACTSनिर्देशिका को भी हटा देगा , जो ठीक है, क्योंकि अगर मैं यह सुनिश्चित करना चाहता हूं कि इसमें कुछ डालने से पहले यह मौजूद है, तो मैं mkdir -p $ARTIFACTSवैसे भी निष्पादित करूंगा । यह भी अंदर छुपा नष्ट करेगा फ़ाइलें $ARTIFACTS, जो भी ठीक है, क्योंकि मैं नहीं लिखते थे rm -rf $ARTIFACTS/*, तो $ARTIFACTSनिहित कुछ भी मैं को बचाने के लिए करना चाहता था।
क्रिस्टोफर हम्मरस्ट्रॉम

@ क्रिस्टोफ़रहमारमस्ट्रम बहुत सही है
मोताज़ एल्माश्री

जवाबों:


9

1. ये दोनों परीक्षण सही हैं :

# [ -d ] && echo true || echo false
true
# [ -d $SOME_UNSET_VAR ] && echo true || echo false
true

POSIX के अनुसार (जैसा कि @Tim द्वारा समझाया गया है)।

2. लेकिन यह गलत है ( प्रश्न में कहा गया सच नहीं है )

# [ -d "" ] && echo true || echo false
false

क्योंकि testदो तर्कों के साथ कहा जाता है (हालांकि दूसरा एक खाली स्ट्रिंग है)।

3. इसीलिए ( ) के [[ … ]]बजाय इसका उपयोग करना अच्छा है , जो कि अधिकांश (सभी?) मौजूदा गोले प्रदान करते हैं। यदि आप पर्याप्त तर्क देते हैं तो यह चेक का निर्माण करता है (अन्यथा एक त्रुटि और गर्भपात फेंकता है)test[ … ]

# [[ -d ]] && echo true || echo false
bash: unexpected argument `]]' to conditional unary operator
bash: syntax error near `]]'

या बस ऐसे व्यवहार करता है जैसे कोई अपेक्षा करता है:

# [[ -d $SOME_UNSET_VAR ]] && echo true || echo false
false

4. और, जैसा कि @Gilles द्वारा बताया गया है, इससे भी अधिक महत्वपूर्ण है डबल कोट प्रतिस्थापन। इसलिए (मामले 2 के बराबर) भी झूठ और -d "$SOME_UNSET_VAR"फैलता है । इसलिए यह बॉर्न शेल के साथ भी संगत है :-d ""testsh

# [ -d "$SOME_UNSET_VAR" ] && echo true || echo false
false

बैश 3.00.16 (1) और 4.1.5 (1) के साथ परीक्षण किया गया


1
बैश, ksh और zsh प्रदान करते हैं [[ … ]]लेकिन सादे नहीं sh। वास्तव में महत्वपूर्ण अभ्यास करने के लिए है आदेश प्रतिस्थापन को दोहरे उद्धरण चिह्नों डाल : [ -d "$ARTIFACTS" ]
गिल्स एसओ- बुराई को रोकना '

6

इस सवाल का जवाब पहले ही StackOverflow पर दिया जा चुका है । यह कहता है कि POSIX मानक के अनुसार, testहमेशा सफल लौटना चाहिए अगर इसे बिल्कुल एक गैर-रिक्त तर्क (और कोई अन्य तर्क) के साथ नहीं कहा जाता है।

यह भी होना चाहिए test -e(और वास्तव में यह मेरे सिस्टम पर है), इसलिए सावधान रहें।

इसके बजाय उपयोग करें:

[ -d "$ARTIFACTS" ]

test तब भी दो तर्कों के साथ बुलाया जाएगा, भले ही चर खाली हो और इस मामले में गलत वापस आए।


"बिल्कुल एक गैर-रिक्त तर्क।" - यह एक भ्रामक सारांश है - जिस पृष्ठ को आपने उल्लेख किया है उसे बिल्कुल एक तर्क के साथ कहा जा रहा है और यह तर्क गैर-रिक्त है; एक खाली के बाद एक गैर-रिक्त तर्क के मामले के बारे में कुछ भी नहीं। सही समाधान उद्धरण में चर नाम को घेरने के लिए होना चाहिए।
रैंडम 832

@ Random832 धन्यवाद! मैंने आपके सुझाए गए परिवर्तनों को लागू किया है।
टिम

[ ! -z $ARTIFACTS ] && [ -d $ARTIFACTS ]कोई बेहतर नहीं है: यह केवल उस विशेष मामले के लिए पूरा करता है जब $ARTIFACTSखाली होता है, लेकिन जब $ARTIFACTSव्हाट्सएप हो सकता है या विफल रहता है \[?*[ -d "$ARTIFACTS" ]यह करने का सही तरीका है (या [[ -d $ARTIFACTS ]]गोले में है [[ … ]])।
गिलेस एसओ- बुराई को रोकना '

@ गिल्स आप सही कह रहे हैं, मैंने इसे हटा दिया। धन्यवाद!
टिम

4

मैंने [-e $ ARTIFACTS] का उपयोग करके समस्या को हल किया जो काम करने लगता है

आप गलत हैं । यह काम करता है क्योंकि $ARTIFACTSअब कुछ करने के लिए सेट है।

जब एक चर सेट नहीं होता है, तो कह रहा है

[ -d $SOMEVAR ]

या

[ -e $SOMEVAR ]

होगा दोनों का मूल्यांकन trueक्योंकि यह कह का तात्पर्य

[ -d ]

तथा

[ -e ]

क्रमशः। (कह रही है[ foobar ] हमेशा सच का मूल्यांकन करेंगे।)

कह रही है

set -u

ऐसी स्थितियों में काम आता है। help setआपको बताएगा:

  -u  Treat unset variables as an error when substituting.

[-ई "" "&& प्रतिध्वनि" प्रिंट समथिंग "कुछ भी प्रिंट नहीं करता है, तो यह गलत कैसे हो सकता है?
मोताज़ एल्माश्री

2
आह कला [-e $ ARTIFACTS] खाली कलाकृतियों की पैदावार के साथ [-ई] नहीं [-ई ""], इसे मिला
Moataz Elmasry

4

देखें कि आपने वेरिएबल ARTIFACTS सेट किया है और आप ARTIFCATS की जाँच कर रहे हैं। शायद गलत व्यवहार कर रहे हैं?

वैसे भी, -d के साथ-साथ unset वैरिएबल पर समान परिणाम उत्पन्न करेगा।

इसलिए दोहरे उद्धरण चिह्नों का उपयोग करें और यह आपकी सहायता करेगा।

ARTIFACTS="/SOME/PATH"
[ -d "$ARTIFACTS" ] && rm -rf -- "$ARTIFACTS/"*

नोट: यदि आपके "/ SOME / PATH" के पास कोई फ़ोल्डर है, तो आपके द्वारा उल्लिखित स्क्रिप्ट "बाइनरी ऑपरेटर द्वारा अपेक्षित" त्रुटि के साथ टूट जाएगी।

उदाहरण:

ARTIFACTS="/home backup/"

1) [ -d $ARTIFACTS ] && rm -rf $ARTIFACTS/*
bash: [: /home: binary operator expected

2) [ -d "$ARTIFACTS" ] && rm -rf "$ARTIFACTS"/*

ठीक कर देंगे। के rmरूप में अच्छी तरह से आह्वान में उद्धरण डाल मत भूलना ( rm -rf $ARTIFACTSख़ुशी से हटा देंगे /homeतो शिकायत करें backup/*कि मौजूदा नहीं है)।

इसके अलावा, -Lचेक सहित यह सुनिश्चित करेगा कि यह एक निर्देशिका है और न केवल एक निर्देशिका का प्रतीकात्मक लिंक है।

तो मूल रूप से,

[ -d "$ARTIFACTS" && ! -L "$ARTIFACTS" ] && rm -rf -- "$ARTIFACTS"/*
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.