सवाल जांचें कि शेल स्क्रिप्ट में कोई निर्देशिका मौजूद है या नहीं


एक शेल स्क्रिप्ट के भीतर, निर्देशिका मौजूद है या नहीं, यह जांचने के लिए किस कमांड का उपयोग किया जा सकता है?


2999
2017-09-12 20:06


मूल




जवाब:


यह जांचने के लिए कि कोई निर्देशिका स्क्रिप्ट स्क्रिप्ट में मौजूद है या नहीं, आप निम्न का उपयोग कर सकते हैं:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

या यह जांचने के लिए कि कोई निर्देशिका मौजूद नहीं है या नहीं:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

हालांकि, के रूप में जॉन एरिक्सन बताते हैं कि बाद के आदेश इरादे से काम नहीं कर सकते हैं यदि आप इस बात पर ध्यान नहीं देते हैं कि निर्देशिका के लिए एक प्रतीकात्मक लिंक भी इस चेक को पास करेगा। जैसे यह चल रहा है:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

त्रुटि संदेश उत्पन्न करेगा:

rmdir: failed to remove `symlink': Not a directory

इसलिए प्रतीकात्मक लिंक अलग-अलग इलाज किए जा सकते हैं, यदि बाद के आदेश निर्देशिकाओं की अपेक्षा करते हैं:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

चर को लपेटने के लिए इस्तेमाल किए गए डबल-कोट्स का विशेष नोट लें, इसका कारण 8jean द्वारा समझाया गया है एक और जवाब में

यदि चरों में रिक्त स्थान या अन्य असामान्य वर्ण होते हैं तो यह शायद स्क्रिप्ट को विफल कर देगा।


4144
2017-09-12 20:07



यदि आप जीएनयू टूल्स के साथ इसे सुरक्षित रखना चाहते हैं, तो इसका उपयोग करें -- अत्यधिक अनुशंसित (अंत में विकल्प मार्कर) है। अन्यथा, यदि आपके चर में ऐसा कुछ है जो किसी विकल्प की तरह दिखता है, तो स्क्रिप्ट केवल रिक्त स्थान के साथ विफल हो जाएगी। - Marc Mutz - mmutz
बैश, क्ष, आदि के आधुनिक संस्करणों के लिए [...] एक अंतर्निहित है - fpmurphy1
ध्यान में रखना एक बात है: [ ! -d "$DIRECTORY" ] या तो सच होगा $DIRECTORY मौजूद नहीं है, या अगर कर देता है मौजूद है लेकिन निर्देशिका नहीं है। कुछ इस तरह पर विचार करें if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi; अगर यह असफल हो जाएगा "$DIRECTORY" एक फाइल है (बेशक आपको यह जांचना चाहिए कि क्या mkdir वैसे भी सफल हुआ; असफल होने के कई कारण हैं।) - Keith Thompson
यह उल्लेखनीय हो सकता है कि जैसे ही चेक किया गया है, स्थिति अन्य प्रक्रियाओं के कारण पहले ही बदल सकती है। कई मामलों में केवल निर्देशिका बनाने या उपयोग करना बेहतर होता है और विफलता पर प्रतिक्रिया होती है। - Alfe
दोनों निर्देशिकाओं के परीक्षण के बजाय (-d) और symlink (-L), वैरिएबल को स्लैश जोड़ने के लिए बस इतना आसान है if [ -d "${THING:+$THING/}" ]। एक निर्देशिका अतिरिक्त स्लैश को ध्यान में रखेगी। एक फ़ाइल झूठी मूल्यांकन करेगा। खाली खाली रहेगा, तो झूठा। और एक सिम्लिंक अपने गंतव्य के लिए हल किया जाएगा। बेशक, यह आपके लक्ष्य पर निर्भर करता है। यदि आप चाहते हैं चले जाओ वहां, यह ठीक है। यदि आप चाहते हैं इसे मिटाओ, तो इस जवाब में कोड बेहतर है। - ghoti


उन्हें संदर्भित करते समय डबल कोट्स में चर को हमेशा लपेटना याद रखें एक बैश स्क्रिप्ट। बच्चे इन दिनों इस विचार के साथ बड़े हो जाते हैं कि उनके पास उनके निर्देशिका नामों में रिक्त स्थान और अन्य मज़ेदार पात्र हो सकते हैं। (रिक्त स्थान! मेरे दिनों में, हमारे पास कोई फैंसी रिक्त स्थान नहीं था!))

एक दिन, उनमें से एक बच्चा आपकी स्क्रिप्ट को साथ चलाएगा $DIRECTORY करने के लिए सेट "My M0viez" और आपकी लिपि उड़ाएगी। आप वह नहीं चाहते हैं। तो इसका इस्तेमाल करें।

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

454
2017-09-15 22:00



डबल कोट्स का उपयोग करने का एक और कारण यह है कि $ DIRECTORY किसी कारण से सेट नहीं है। - Jon Ericson♦
"हमेशा डबल कोट्स में चर को लपेटें ... एक बैश स्क्रिप्ट में।" [[...]] का उपयोग करते समय तकनीकी रूप से आवश्यक नहीं है; देख tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS (नोट: कोई शब्द विभाजित नहीं है): "[/ और]] के बीच कोई फ़ाइल नाम विस्तार या शब्द विभाजन नहीं होता है, लेकिन पैरामीटर विस्तार और कमांड प्रतिस्थापन है।" - michael
यूनिक्स / लिनक्स पर निर्देशिकाओं में कोई सफेद जगह नहीं होनी चाहिए, और बाद में स्क्रिप्ट को इसे अनुकूलित नहीं किया जाना चाहिए। यह विंडोज़ स्क्रिप्टिंग के सभी परिणामों के साथ विंडोज़ का समर्थन करता है, लेकिन कृपया, जो कुछ भी हो, उसके लिए अनावश्यक आवश्यकताओं को पेश करने की आवश्यकता नहीं है। - tvCa
@tvCa मुझे लगता है कि डेवलपर्स के लिए चीजों को आसान बनाने के लिए मजबूर होने के बजाए उपयोगकर्ता आमतौर पर अपनी निर्देशिका नामों में अधिक लचीलापन की अनुमति देना पसंद करते हैं। (वास्तव में, लंबे फ़ाइल नामों से निपटने के दौरान, मुझे बिना किसी जगह के दर्द होता है, जो शब्द लपेटने को मारता है, भले ही मैंने खुद को अतीत में पीड़ितों और कार्यक्रमों में रिक्त स्थान के पथों के लिए लेखांकन नहीं किया है।) - JAB
हा। रिक्त स्थान केवल वे अक्षर हैं जिनके पास आमतौर पर कोई ग्लिफ नहीं होता है। वैसे भी, आप उन्हें बैकस्लैश से बच सकते हैं। - uchuugaka


ध्यान दें -d परीक्षण कुछ आश्चर्यजनक परिणाम उत्पन्न कर सकते हैं:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

फ़ाइल के अंतर्गत: "निर्देशिका कब निर्देशिका नहीं है?" उत्तर: "जब यह एक निर्देशिका के लिए एक सिम्लिंक है।" थोड़ा और गहन परीक्षण:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

आप बैश मैनुअल में अधिक जानकारी प्राप्त कर सकते हैं बैश सशर्त अभिव्यक्तियां और यह [ बिल्टिन कमांड और यह [[ यौगिक कमांड


204
2017-09-12 20:26



या, यह मानते हुए कि निर्देशिकाओं पर काम करना केवल आवश्यक है (और लिंक को अनदेखा किया जा सकता है) => if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi ... या, एक आदेश के लिए जो दोनों लिंक और dirs पर काम करता है: rm -r tmpdir - michael


मुझे लगता है डबल ब्रैकेट का संस्करण test लेखन तर्क परीक्षण अधिक प्राकृतिक बनाता है:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

198
2017-09-12 21:33



के लिये if [[ -d "$TARFILE" ]] मुझे मिल रहा है [[: नहीं मिला - TheVillageIdiot
ditto [[: नहीं मिला - Hedgehog
@TheVillageIdiot और @ हेजहोग, क्या आप बैश खोल का उपयोग कर रहे हैं? डबल ब्रैकेट सार्वभौमिक रूप से समर्थित नहीं है। उस बिंदु पर एक SO उत्तर दिया गया है: stackoverflow.com/questions/669452/... - yukondude
और डिफ़ॉल्ट संकलन विकल्पों के साथ Busybox राख में [[ ]] समर्थित है, लेकिन वास्तव में कोई अलग कार्यक्षमता प्रदान नहीं करता है [ ]। अगर पोर्टेबिलिटी चिंता का विषय है, तो चिपके रहें [ ] और आवश्यक कामकाज का उपयोग करें। - dubiousjim
... यदि शेल स्क्रिप्ट में बैश संरचनाओं का उपयोग करना है, तो स्क्रिप्ट की पहली पंक्ति होना चाहिए: #! / bin / bash (और नहीं #! / bin / sh, ksh, आदि) - michael


छोटा रूप:

[ -d "$DIR" ] && echo "Yes"

125
2017-09-12 21:08



क्या यह इस तरह काम करता है: if $dir is a dir, then echo "yes"? स्पष्टीकरण की एक बिट मदद करेगा :) - Martijn
cmd && other के लिए एक आम शॉर्टेंड है if cmd; then other; fi - यह अधिकांश प्रोग्रामिंग भाषाओं के साथ काम करता है जो बूलियन तर्क का समर्थन करते हैं, और इसके रूप में जाना जाता है शॉर्ट सर्किट मूल्यांकन। - tripleee
व्यवहार एक जैसा नहीं है set -e (जो कि है शैल प्रोग्रामिंग सर्वोत्तम अभ्यास)। - dolmen


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

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

आप इसे नकारात्मक में भी कर सकते हैं

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

ध्यान दें: सावधान रहें, दोनों खुले और बंद ब्रेसिज़ के दोनों तरफ खाली रिक्त स्थान छोड़ दें।

उसी वाक्यविन्यास के साथ आप इसका उपयोग कर सकते हैं:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 

119
2018-04-08 02:50





if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi

94
2018-04-15 08:07





आप उपयोग कर सकते हैं test -d (देख man test)।

-d file       सही है अगर फ़ाइल मौजूद है और एक निर्देशिका है।

उदाहरण के लिए:

test -d "/etc" && echo Exists || echo Does not exist

ध्यान दें test आदेश सशर्त अभिव्यक्ति के समान है [ (देख: man [), तो यह खोल स्क्रिप्ट में पोर्टेबल है।

[ - यह एक पर्याय है test बिल्टिन, लेकिन अंतिम तर्क एक शाब्दिक होना चाहिए ], उद्घाटन से मेल खाने के लिए [

संभावित विकल्पों या आगे की सहायता के लिए, जांचें:

  • help [
  • help test
  • man test या man [

74
2017-09-12 21:25





या कुछ पूरी तरह से बेकार के लिए:

[ -d . ] || echo "No"

55
2017-08-17 14:02



यह कभी भी "नहीं" प्रिंट करेगा। वर्तमान निर्देशिका हमेशा मौजूद है, जब तक कि किसी अन्य धागे या अन्य तरीकों से हटाया न जाए। - Jahid
सही नमूना :) दिया गया है कि स्वीकार किए गए उत्तर की तुलना में "अद्वितीय" कुछ जवाब कैसे हैं - Sergey Sargsyan
यह इतनी बार क्यों उखाड़ फेंक दिया गया है? यह सवाल का जवाब नहीं देता है। - codeforester


यहां एक बहुत व्यावहारिक मुहावरे है:

(cd $dir) || return # is this a directory,
                    # and do we have access?

मैं आमतौर पर इसे एक समारोह में लपेटता हूं:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

या:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

इस दृष्टिकोण के बारे में अच्छी बात यह है कि मुझे एक अच्छा त्रुटि संदेश नहीं सोचना है।

cd मुझे पहले से ही stderr के लिए एक मानक एक लाइन संदेश दे देंगे। इससे अधिक जानकारी भी मिल जाएगी जो मैं प्रदान करने में सक्षम हूं। प्रदर्शन करके cd एक सबहेल के अंदर ( ... ), आदेश कॉलर की वर्तमान निर्देशिका को प्रभावित नहीं करता है। यदि निर्देशिका मौजूद है, तो यह सबहेल और फ़ंक्शन केवल एक नो-ऑप है।

अगला तर्क है कि हम पास करते हैं cd: ${1:?pathname expected}। यह पैरामीटर प्रतिस्थापन का एक और विस्तृत रूप है जिसे नीचे अधिक विस्तार से समझाया गया है।

टीएल; डॉ: यदि इस फ़ंक्शन में पारित स्ट्रिंग खाली है, तो हम फिर से सबहेल से बाहर निकलेंगे ( ... ) और दिए गए त्रुटि संदेश के साथ समारोह से वापस आते हैं।


से उद्धरण ksh93 मैन पेज:

${parameter:?word}

अगर parameter  सेट है और गैर-शून्य है तो इसके मूल्य को प्रतिस्थापित करें;   अन्यथा, प्रिंट करें word और खोल से बाहर निकलें (यदि इंटरैक्टिव नहीं है)।   अगर word छोड़ा जाता है तो एक मानक संदेश मुद्रित किया जाता है।

तथा

अगर कोलन : उपर्युक्त अभिव्यक्तियों से छोड़ा गया है, फिर   खोल केवल जांचता है कि पैरामीटर सेट है या नहीं।

यहाँ phrasing खोल दस्तावेज के लिए असाधारण है, के रूप में word संदर्भित कर सकते हैं व्हाइटस्पेस सहित किसी भी उचित स्ट्रिंग के लिए।

इस विशेष मामले में, मुझे पता है कि मानक त्रुटि संदेश 1: parameter not set पर्याप्त नहीं है, इसलिए मैं उस मूल्य के प्रकार पर ज़ूम इन करता हूं जिसे हम यहां उम्मीद करते हैं - pathname एक निर्देशिका का।

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


46
2017-08-09 21:43



यह केवल अस्तित्व की जांच करने से अधिक है: यह आपके उपयोगकर्ता स्तर पर पहुंच के लिए यह जांच। SO सवाल के लिए खड़े हो जाओ अस्तित्व केवल। तो सही जवाब है test -d @Grundlefleck के रूप में समझाया। - F. Hauri
@ एफ। हॉरी - उसने और कुछ नहीं पूछा, यह सच है। हालांकि, मैंने पाया है कि मुझे आमतौर पर उससे अधिक जानने की आवश्यकता है। - Henk Langeveld
और यह मेरे लिए कभी नहीं हुआ कि कोई परीक्षण निर्णायक नहीं हो सकता है, जब तक यह रूट के रूप में नहीं चलता है। test -d /unreadable/exists असफल हो जाएगा, भले ही तर्क मौजूद है। - Henk Langeveld