अगर कोई प्रोग्राम बैश स्क्रिप्ट से मौजूद है तो मैं कैसे जांच सकता हूं?


2207

मैं कैसे पुष्टि करूंगा कि एक कार्यक्रम मौजूद है, एक तरह से जो या तो एक त्रुटि और निकास लौटेगा, या स्क्रिप्ट के साथ जारी रहेगा?

ऐसा लगता है कि यह आसान होना चाहिए, लेकिन यह मुझे स्टम्पिंग कर रहा है।


एक "कार्यक्रम" क्या है? क्या इसमें फ़ंक्शन और उपनाम शामिल हैं? whichइनके लिए सही है। typeबिना तर्कों के अतिरिक्त आरक्षित शब्दों और शेल बिल्डरों के लिए सही वापसी होगी। यदि "प्रोग्राम" का अर्थ है "बहने योग्य $PATH", तो यह उत्तर देखें ।
टॉम हेल

जवाबों:


3045

उत्तर

POSIX संगत:

command -v <the_command>

बैश विशिष्ट वातावरण के लिए:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

व्याख्या

से बचें which। न केवल यह एक बाहरी प्रक्रिया है जिसे आप बहुत कम करने के लिए लॉन्च कर रहे हैं (मतलब बिल्‍डेंस जैसे hash, typeया commandरास्‍ते सस्‍ते हैं), आप बिल्‍डर पर भी भरोसा कर सकते हैं कि वास्‍तव में आप क्‍या चाहते हैं, जबकि बाहरी कमांड के प्रभाव आसानी से अलग हो सकते हैं सिस्टम से सिस्टम।

परवाह क्यों?

  • कई ऑपरेटिंग सिस्टम एक है whichकि यहां तक कि एक निकास स्थिति निर्धारित नहीं करता है , जिसका अर्थ है if which fooभी वहाँ काम नहीं करेगा और होगा हमेशा की रिपोर्ट है कि fooमौजूद है, भले ही वह (ध्यान दें कि कुछ POSIX गोले के लिए यह करने के लिए प्रकट नहीं होता है hashभी)।
  • कई ऑपरेटिंग सिस्टम whichकस्टम और बुरी चीजें करते हैं जैसे आउटपुट को बदलते हैं या यहां तक ​​कि पैकेज मैनेजर में भी हुक लगाते हैं।

तो, उपयोग नहीं करते which। इसके बजाय इनमें से किसी एक का उपयोग करें:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(माइनर साइड-नोट: कुछ सुझाएगा 2>&-वही है 2>/dev/nullलेकिन छोटा है - यह असत्य है2>&-एफडी 2 को बंद कर देता है जो प्रोग्राम में एक त्रुटि का कारण बनता है जब यह स्टडर को लिखने की कोशिश करता है, जो इसे सफलतापूर्वक लिखने और आउटपुट को छोड़ने से बहुत अलग है। (और खतरनाक!))

यदि आपका हैश बैंग है /bin/shतो आपको इस बात की परवाह करनी चाहिए कि POSIX क्या कहता है। typeऔर hashबाहर निकलने के कोड बहुत अच्छी तरह से POSIX द्वारा परिभाषित नहीं हैं, और hashजब कमांड मौजूद नहीं है तो सफलतापूर्वक बाहर निकलने के लिए देखा जाता है ( typeअभी तक इसे नहीं देखा है)। commandPOSIX द्वारा बाहर निकलने की स्थिति को अच्छी तरह से परिभाषित किया गया है, ताकि कोई संभवतः उपयोग करने के लिए सबसे सुरक्षित हो।

अपनी स्क्रिप्ट का उपयोग करता है, तो bashहालांकि, POSIX नियम वास्तव में बात अब और नहीं है और दोनों typeऔर hashपूरी तरह से उपयोग करने के लिए सुरक्षित हो जाते हैं। typeअब एक है -Pखोजने के लिए बस PATHऔरhash इसका साइड-इफेक्ट है कि कमांड का स्थान हैशेड हो जाएगा (अगली बार जब आप इसे उपयोग करते हैं तो तेजी से देखने के लिए), जो आमतौर पर एक अच्छी बात है क्योंकि आप वास्तव में इसका उपयोग करने के लिए इसके अस्तित्व की जांच करते हैं। ।

एक सरल उदाहरण के रूप में, यहां एक फ़ंक्शन है जो gdateअगर मौजूद है, तो चलता है date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

34
@Geert: The &> / dev / null हिस्सा संदेश छिपाता है 'टाइप' का उत्सर्जन तब होता है जब 'foo' मौजूद नहीं होता है। गूंज पर> & 2 मानक आउटपुट के बजाय त्रुटि संदेश को मानक त्रुटि पर भेजना सुनिश्चित करता है; क्योंकि वह सम्मेलन है। वे दोनों आपके टर्मिनल पर दिखाई देते हैं, लेकिन त्रुटि संदेशों और अप्रत्याशित चेतावनियों के लिए मानक त्रुटि निश्चित रूप से पसंदीदा आउटपुट है।
लुनानाथ

5
-पी ध्वज 'श' में काम नहीं करता है, उदाहरण के लिए stackoverflow.com/questions/2608688/…
Momeara

128
उन लोगों के लिए जो 'उन्नत' i / o बैश में पुनर्निर्देशन से अपरिचित हैं: 1) 2>&- ("क्लोज़ आउटपुट फ़ाइल डिस्क्रिप्टर 2", जो कि stderr है) के समान परिणाम है 2> /dev/null; 2) >&2एक शॉर्टकट है 1>&2, जिसे आप "रेडर स्टडआउट टू स्टडर" के रूप में पहचान सकते हैं। देखें उन्नत बैश पटकथा गाइड आई / ओ पुनर्निर्देशन पेज अधिक जानकारी के लिए।
mikewaters

9
@mikewaters एबीएस काफी उन्नत दिखता है और बैश और नॉन-बैश सीएलआई कार्यक्षमता की एक विस्तृत श्रृंखला का वर्णन करता है, लेकिन यह कई पहलुओं में बहुत लापरवाही करता है और अच्छे अभ्यास का पालन नहीं करता है। इस टिप्पणी में लिखने के लिए लगभग पर्याप्त जगह नहीं है; लेकिन मैं खराब कोड की कुछ यादृच्छिक उदाहरण पेस्ट कर सकते हैं: while read element ; do .. done <<< $(echo ${ArrayVar[*]}), for word in $(fgrep -l $ORIGINAL *.txt), ls -l "$directory" | sed 1d , {{के लिए एक में seq $BEGIN $END}} ... कई लेखकों से संपर्क करें और सुधार का प्रस्ताव करने की कोशिश की है, लेकिन यह कोई विकी है और अनुरोध बहरा कान पर पहुँचे हैं।
20

56
@mikewaters 2>&-जैसा नहीं है 2>/dev/null। पूर्व फ़ाइल डिस्क्रिप्टर को बंद कर देता है, जबकि बाद वाला इसे केवल रीडायरेक्ट करता है /dev/null। आपको कोई त्रुटि दिखाई नहीं दे सकती क्योंकि प्रोग्राम आपको stderr पर सूचित करने का प्रयास करता है कि stderr बंद है।
nyuszika7h

574

यह जाँचने का एक पोर्टेबल तरीका है कि क्या कोई कमांड मौजूद है $PATH और निष्पादन योग्य है:

[ -x "$(command -v foo)" ]

उदाहरण:

if ! [ -x "$(command -v git)" ]; then
  echo 'Error: git is not installed.' >&2
  exit 1
fi

निष्पादन योग्य चेक की आवश्यकता है क्योंकि बैश एक गैर-निष्पादन योग्य फ़ाइल देता है यदि उस नाम के साथ कोई निष्पादन योग्य फ़ाइल नहीं मिलती है $PATH

यह भी ध्यान दें कि यदि निष्पादन योग्य नाम के साथ एक गैर-निष्पादन योग्य फ़ाइल पहले से मौजूद है $PATH, तो डैश पूर्व को वापस कर देता है, भले ही बाद में निष्पादित किया जाएगा। यह एक बग है और POSIX मानक के उल्लंघन में है। [ बग रिपोर्ट ] [ मानक ]

इसके अलावा, यह विफल हो जाएगा यदि आप जिस कमांड की तलाश कर रहे हैं उसे एक उपनाम के रूप में परिभाषित किया गया है।


4
command -vएक गैर-निष्पादन योग्य फ़ाइल के लिए भी एक पथ का उत्पादन करेगा ? यही है, -x वास्तव में आवश्यक है?
einpoklum

5
@einpoklum -xपरीक्षण करता है कि फ़ाइल निष्पादन योग्य है, जो कि प्रश्न था।
केन शार्प

3
@KenSharp: लेकिन यह बेमानी लग रहा है, क्योंकि commandखुद इसके निष्पादन योग्य होने के लिए परीक्षण करेगा - क्या यह नहीं होगा?
ईनपोक्लुम

13
@einpoklum हाँ, यह आवश्यक है। वास्तव में, यहां तक ​​कि यह समाधान एक किनारे के मामले में टूट सकता है। इसे मेरे संज्ञान में लाने के लिए धन्यवाद। $PATHजब कोई कमांड निष्पादित करता है तो डैश, बैश और zsh सभी गैर-निष्पादन योग्य फ़ाइलों को छोड़ देते हैं । हालाँकि, का व्यवहार command -vबहुत असंगत है। डैश में, यह $PATHनिष्पादन योग्य पहली फ़ाइल देता है , भले ही यह निष्पादन योग्य हो या नहीं। बैश में, यह पहला निष्पादन योग्य मैच देता है $PATH, लेकिन यदि कोई नहीं है, तो यह एक गैर-निष्पादन योग्य फ़ाइल लौटा सकता है। और zsh में, यह एक गैर-निष्पादन योग्य फ़ाइल कभी नहीं लौटाएगा।
nyuszika7h 13

4
जहां तक ​​मैं बता सकता हूं, dashउन तीनों में से केवल एक ही है जो गैर-पॉसिक्स-आज्ञाकारी है; [ -x "$(command -v COMMANDNAME)"]अन्य दो में काम करेंगे। ऐसा लगता है कि यह बग पहले ही रिपोर्ट किया जा चुका है, लेकिन अभी तक कोई प्रतिक्रिया नहीं मिली है: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
nyuszika7h

208

मैं लूनाथ से सहमत हूं कि वे इसके उपयोग को हतोत्साहित करें whichऔर बश उपयोगकर्ताओं के लिए उसका समाधान पूरी तरह से मान्य है । हालाँकि, अधिक पोर्टेबल command -vहोने के बजाय , इसका उपयोग किया जाएगा:

$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed.  Aborting." >&2; exit 1; }

कमांड commandPOSIX अनुपालन है। इसके विनिर्देशन के लिए यहां देखें: कमांड - एक साधारण कमांड निष्पादित करें

नोट: typePOSIX शिकायत है, लेकिन type -Pनहीं है।


3
ऊपर के रूप में भी - exit 1;एक xterm को मारता है, अगर वहां से आह्वान किया जाता है।
उपयोगकर्ता अज्ञात

1
यह मानक श पर काम नहीं करेगा: आप &> एक वैध पुनर्निर्देशन निर्देश नहीं है।
jyavenard

7
@jyavenard: प्रश्न को टैग किया गया बैश है , इसलिए अधिक संक्षिप्त बैश-विशिष्ट रीडायरेक्ट नोटेशन है &>/dev/null। हालाँकि, मैं आपसे सहमत हूँ, जो वास्तव में मायने रखता है, वह है पोर्टेबिलिटी, मैंने अपने उत्तर को उसी हिसाब से संपादित किया है, अब मानक sh पुनर्निर्देशन का उपयोग कर रहा हूँ >/dev/null 2>&1
ग्रेग

इस उत्तर को और अधिक बेहतर बनाने के लिए मैं दो चीजों को करूंगा: 1: "&>" का उपयोग इसे सरल बनाने के लिए, जोश के उत्तर की तरह। 2: एक अतिरिक्त लाइन में {} को
तोड़ो

मैं सिर्फ एक लाइनर को बैश फंक्शन में डालता हूं अगर कोई इसे चाहे तो ... github.com/equant/my_bash_tools/blob/master/tarp.bash
बराबर

94

मेरे पास मेरे .bashrc में एक फ़ंक्शन परिभाषित है जो इसे आसान बनाता है।

command_exists () {
    type "$1" &> /dev/null ;
}

इसका उपयोग कैसे किया जाता है (मेरे .bash_profile)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi

क्या करता &>है?
साद मलिक


&>आपके बैश के संस्करण में उपलब्ध नहीं हो सकता है। मार्सेलो का कोड ठीक काम करना चाहिए; यह वही काम करता है।
जोश स्ट्रैटर

3
बिल्डिंस और आरक्षित शब्दों पर विफल: thenउदाहरण के लिए इस शब्द के साथ प्रयास करें । यदि आपको निष्पादन योग्य होने की आवश्यकता है तो इस उत्तर को देखें $PATH
टॉम हेल

84

यह इस बात पर निर्भर करता है कि आप यह जानना चाहते हैं कि क्या यह $PATHचर में मौजूद किसी निर्देशिका में मौजूद है या नहीं और आपको इसका सही स्थान पता है या नहीं। यदि आप जानना चाहते हैं कि क्या यह $PATHचर में है, तो उपयोग करें

if which programname >/dev/null; then
    echo exists
else
    echo does not exist
fi

अन्यथा उपयोग करें

if [ -x /path/to/programname ]; then
    echo exists
else
    echo does not exist
fi

/dev/null/पहले उदाहरण में पुनर्निर्देशन whichकार्यक्रम के आउटपुट को दबा देता है ।


22
मेरी टिप्पणी में उल्लिखित कारणों के लिए आपको वास्तव में "जो" का उपयोग नहीं करना चाहिए।
लूनाथ

39

@ Lhunath's और @ GregV के उत्तरों पर विस्तार करते हुए, यहां उन लोगों के लिए कोड दिया गया है, जो आसानी से यह जानना चाहते हैं if:

exists()
{
  command -v "$1" >/dev/null 2>&1
}

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

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi

13
सीखने और सुधारने की इच्छा को पुरस्कृत किया जाना चाहिए। +1 यह साफ और सरल है। केवल एक चीज जो मैं जोड़ सकता हूं वह यह है कि commandउपनाम के लिए भी सफल होता है, जो कुछ हद तक प्रतिवाद हो सकता है। एक इंटरैक्टिव शेल में अस्तित्व के लिए जाँच करने से अलग-अलग परिणाम मिलेंगे जब आप इसे किसी स्क्रिप्ट में स्थानांतरित करेंगे।
पालक

1
मैंने अभी-अभी परीक्षण किया है और shopt -u expand_aliasesअलिज़र्स / हाइड्स (जैसे alias ls='ls -F'किसी अन्य उत्तर में उल्लिखित) का उपयोग करके परीक्षण किया है और shopt -s expand_aliasesउनके माध्यम से हल करता है command -v। तो शायद यह चेक से पहले सेट किया जाना चाहिए और बाद में परेशान होना चाहिए, हालांकि यह फ़ंक्शन रिटर्न मान को प्रभावित कर सकता है यदि आप कैप्चर नहीं करते हैं और कमांड कॉल का आउटपुट स्पष्ट रूप से वापस करते हैं।
ड्रैगन

24

प्रयोग करके देखें:

test -x filename

या

[ -x filename ]

सशर्त अभिव्यक्तियों के तहत बैश मैनपेज से :

 -x file
          True if file exists and is executable.

26
इसका मतलब है कि आपको पहले से ही आवेदन का पूरा रास्ता पता होना चाहिए।
लहुनाथ

12
यदि वह किसी विशिष्ट उदाहरण या किसी निष्पादन योग्य उदाहरण के लिए जाँच करना चाहता था, तो ओपी ने निर्दिष्ट नहीं किया था ... मैंने उसे उसी तरह से उत्तर दिया जैसे मैंने उसे पढ़ा था।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

16

का उपयोग करने के लिए hash, @ ल्हुनाथ का सुझाव है , एक बैश स्क्रिप्ट में:

hash foo &> /dev/null
if [ $? -eq 1 ]; then
    echo >&2 "foo not found."
fi

यह स्क्रिप्ट चलती है hashऔर फिर जांचती है कि सबसे हालिया कमांड का एक्जिट कोड, में संग्रहीत मूल्य के $?बराबर है या नहीं 1। यदि hashनहीं मिलता है foo, तो बाहर निकलने का कोड होगा 1। यदि fooमौजूद है, तो निकास कोड होगा 0

&> /dev/nullमानक त्रुटि और मानक आउटपुट को रीडायरेक्ट hashकरता है ताकि वह ऑनस्क्रीन दिखाई न दे और echo >&2मानक त्रुटि पर संदेश लिखता है।


8
सिर्फ क्यों नहीं if hash foo &> /dev/null; then ...?
बेनी चेर्नियाव्स्की-पास्किन

9

मुझे उस बॉक्स पर काम करने के लिए पिछले उत्तर कभी नहीं मिले जिनकी मुझे पहुँच है। एक के लिए, typeस्थापित किया गया है (क्या moreकरता है)। इसलिए बिल्टइन डायरेक्शन की जरूरत है। यह कमांड मेरे लिए काम करती है:

if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi

3
ब्रैकेट ifसिंटैक्स का हिस्सा नहीं है , बस उपयोग करें if builtin type -p vim; then ...। और backticks वास्तव में प्राचीन और पदावनत सिंटैक्स हैं, सभी आधुनिक प्रणालियों $()द्वारा भी समर्थित shहैं।
nyuszika7h

9

कई निर्भरता के लिए जाँच करें और उपयोगकर्ताओं को समाप्त करने के लिए स्थिति को सूचित करें

for cmd in latex pandoc; do
  printf '%-10s' "$cmd"
  if hash "$cmd" 2>/dev/null; then
    echo OK
  else
    echo missing
  fi
done

नमूना उत्पादन:

latex     OK
pandoc    missing

10अधिकतम कमांड लंबाई को समायोजित करें । यह स्वचालित नहीं है, क्योंकि मुझे इसे करने के लिए एक गैर-क्रियात्मक POSIX तरीका नहीं दिखाई देता है: मैं बैश में एक अलग टेबल के कॉलम को कैसे संरेखित कर सकता हूं?

जांचें कि क्या कुछ aptपैकेजों को स्थापित किया गया है dpkg -sऔर अन्यथा उन्हें स्थापित करें

देखें: चेक करें कि क्या apt-get संकुल स्थापित है और यदि लिनक्स पर नहीं है तो इसे स्थापित करें

यह पहले उल्लेख किया गया था: मैं कैसे जांच कर सकता हूं कि क्या कोई प्रोग्राम बैश स्क्रिप्ट से मौजूद है?


1
गैर-क्रियात्मक तरीका इसे करने के लिए: 1) चौड़ाई निर्दिष्ट से छुटकारा पाएं; 2) अपने कमांड नाम के प्रिंटफ के बाद एक स्थान जोड़ें; 3) अपने लूप के लिए पाइप column -t(उपयोग-लिनेक्स का हिस्सा)।
पाट्रिस लेवेस्क

8

यदि आप प्रोग्राम के अस्तित्व की जाँच करते हैं, तो आप शायद इसे बाद में चलाने जा रहे हैं। इसे पहली जगह में चलाने की कोशिश क्यों नहीं की गई?

if foo --version >/dev/null 2>&1; then
    echo Found
else
    echo Not found
fi

यह एक अधिक विश्वसनीय जांच है कि कार्यक्रम केवल पीएटीएच निर्देशिकाओं और फ़ाइल अनुमतियों को देखने से चलता है।

साथ ही आप अपने प्रोग्राम से कुछ उपयोगी परिणाम प्राप्त कर सकते हैं, जैसे कि इसका संस्करण।

बेशक कमियां यह हैं कि कुछ कार्यक्रम शुरू करने के लिए भारी पड़ सकते हैं और कुछ में --versionतुरंत (और सफलतापूर्वक) बाहर निकलने का विकल्प नहीं है ।


6

hash foo 2>/dev/null: Z शेल (Zsh), बैश, डैश और ऐश के साथ काम करता है ।

type -p foo: यह Z शेल, बैश और ऐश ( बिज़ीबॉक्स ) के साथ काम करता प्रतीत होता है , लेकिन डैश नहीं (यह -pएक तर्क के रूप में व्याख्या करता है)।

command -v foo: Z शेल, बैश, डैश के साथ काम करता है, लेकिन ऐश (बिजीबॉक्स) ( -ash: command: not found) नहीं।

यह भी ध्यान दें कि builtinराख और डैश के साथ उपलब्ध नहीं है।


4

यदि आप कर सकते हैं तो बाश बिल्डरों का उपयोग करें:

which programname

...

type -P programname

15
है ना? whichबैश बिलियन नहीं है।
त्रिकाल

type -P programname को प्राथमिकता दी जानी है, स्वीकृत उत्तर देखें
रॉबर्ट जीएल

@ रोबर्ट जी सभी मैं देख रहा हूँ कि -Pपॉसिक्स नहीं है। क्यों type -Pपसंद किया जाता है?
मिकमेकाना

जैसा कि मैंने बाश-विशिष्ट पिछली टिप्पणी का उत्तर देने के इरादे से कहा था कि "मुझे बैश वातावरण में पसंद किया जाना चाहिए"। किसी भी तरह, वह साल पहले था - मुझे लगता है कि मुझे बस, फिर से, आपको "accpeted" के रूप में चिह्नित उत्तर की ओर इंगित करना चाहिए
रॉबर्ट जी

4

-vयदि POSIX_BUILTINS विकल्प सेट है, तो कमांड ठीक काम करती है<command> को जांचने के लिए , लेकिन यह विफल हो सकता है यदि नहीं। (इसने मेरे लिए वर्षों तक काम किया है, लेकिन मैं हाल ही में एक में भाग गया जहां यह काम नहीं किया।)

मुझे लगता है कि निम्नलिखित अधिक विफल हो जाएगा:

test -x $(which <command>)

चूंकि यह तीन चीजों के लिए परीक्षण करता है: पथ, अस्तित्व और निष्पादन की अनुमति।


काम नहीं करता है। test -x $(which ls)रिटर्न 0, करता है test -x $(which sudo), भले ही lsस्थापित किया गया है और runnable और sudoभी डोकर कंटेनर मैं में चल रहा हूँ के भीतर स्थापित नहीं है।
शैवाल

@algal आपको मेरे विचार से उद्धरणों का उपयोग करने की आवश्यकता है, इसलिएtest -x "$(which <command>)"
JoniVR

@algal शायद अलियास lsहै? मुझे नहीं लगता कि अगर कमांड में पैरामीटर है तो यह काम करेगा।
एंथोनीसी

3

रुचि रखने वालों के लिए, पिछले उत्तरों में कोई भी कार्यप्रणाली काम नहीं करती है यदि आप एक स्थापित पुस्तकालय का पता लगाना चाहते हैं। मैं कल्पना करता हूं कि आप या तो शारीरिक रूप से पथ की जांच कर रहे हैं (हेडर फ़ाइलों और इस तरह के लिए), या ऐसा कुछ (यदि आप डेबियन-आधारित वितरण पर हैं):

dpkg --status libdb-dev | grep -q not-installed

if [ $? -eq 0 ]; then
    apt-get install libdb-dev
fi

जैसा कि आप ऊपर से देख सकते हैं, क्वेरी से "0" उत्तर का मतलब पैकेज स्थापित नहीं है। यह "grep" का एक फ़ंक्शन है - एक "0" का अर्थ है एक मैच पाया गया था, एक "1" का मतलब है कि कोई मैच नहीं मिला।


10
हालांकि, विरोधी पैटर्न cmd; if [ $? -eq 0 ]; thenको if cmd; then
ट्रिपल

यह केवल काम के लिए dpkgया के माध्यम से स्थापित करने के लिए काम करता हैapt
Weijun झोउ

3

यहां विकल्पों में से एक टन है, लेकिन मुझे आश्चर्य नहीं हुआ कि कोई भी एक-लाइनर नहीं था। यह वही है जो मैंने अपनी लिपियों की शुरुआत में इस्तेमाल किया था:

[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }

यह यहां चयनित उत्तर और एक अन्य स्रोत पर आधारित है।


2

मैं कहूँगा कि किसी भी पोर्टेबल और 100% विश्वसनीय तरीके से झूलने के कारण नहीं है alias। उदाहरण के लिए:

alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/

बेशक, केवल आखिरी समस्याग्रस्त है (रिंगो के लिए कोई अपराध नहीं!)। लेकिन वे सभी के aliasदृष्टिकोण से मान्य हैं command -v

जैसे झूलने वालों को अस्वीकार करने के लिए ringo, हमें शेल में निर्मित aliasकमांड के आउटपुट को पार्स करना होगा और उनमें पुनरावृत्ति करना होगा (यहां से command -vबेहतर नहीं aliasहै।) इसके लिए कोई पोर्टेबल समाधान नहीं है, और यहां तक ​​कि बैश भी नहीं है। विशिष्ट समाधान बल्कि थकाऊ है।

ध्यान दें कि इस तरह एक समाधान बिना शर्त अस्वीकार कर देगा alias ls='ls -F':

test() { command -v $1 | grep -qv alias }

अच्छी बात। हालांकि, जब एक बैश स्क्रिप्ट के अंदर से चलाया जाता है, तो उपनाम दिखाई नहीं देते हैं।
तुलसी मूसा

1
एक समस्या यह भी है, यह गलत होगा जब कमांड 'उर्फ' की जाँच की जाएगी। जब यह सच लौटना चाहिए। उदाहरण: परीक्षण "उर्फ"
तुलसी मूसा

2
मैंने अभी-अभी shopt -u expand_aliasesइन एलियनों को इग्नोर किया / छुपाया और इनका प्रयोग करके shopt -s expand_aliasesदिखाया command -v
ड्रैगन 788

1

whichआदेश उपयोगी हो सकता है। आदमी जो

यदि निष्पादन योग्य पाया जाता है तो यह 0 देता है और यदि निष्पादन योग्य नहीं है तो यह 1 रिटर्न देता है:

NAME

       which - locate a command

SYNOPSIS

       which [-a] filename ...

DESCRIPTION

       which returns the pathnames of the files which would
       be executed in the current environment, had its
       arguments been given as commands in a strictly
       POSIX-conformant shell. It does this by searching
       the PATH for executable files matching the names
       of the arguments.

OPTIONS

       -a     print all matching pathnames of each argument

EXIT STATUS

       0      if all specified commands are 
              found and executable

       1      if one or more specified commands is nonexistent
              or not executable

       2      if an invalid option is specified

इसके बारे whichमें अच्छी बात यह है कि यह पता चलता है कि निष्पादन योग्य वातावरण में उपलब्ध है जो इसमें whichचलाया जाता है - यह कुछ समस्याओं को बचाता है ...


जिसका उपयोग अगर आप फू नाम के किसी भी निष्पादन योग्य के लिए देख रहे हैं, लेकिन मेरा उत्तर देखें यदि आप किसी विशेष फ़ाइल / पथ / को / a / नाम / foo की जांच करना चाहते हैं। यह भी ध्यान दें कि जो कुछ न्यूनतम प्रणालियों पर उपलब्ध नहीं हो सकता है, हालांकि यह किसी भी पूर्ण इंस्टॉलेशन पर मौजूद होना चाहिए ...
dmckee --- पूर्व-मध्यस्थ बिल्ली का बच्चा

9
बाहर निकलने की स्थिति पर भरोसा मत करो। कई ऑपरेटिंग सिस्टमों में एक ऐसा है जो
0.46 के

1

डेबियन सर्वर के लिए मेरा सेटअप :

मुझे समस्या तब हुई जब कई पैकेजों में एक ही नाम था।

उदाहरण के लिए apache2। तो यह था मेरा हल:

function _apt_install() {
    apt-get install -y $1 > /dev/null
}

function _apt_install_norecommends() {
    apt-get install -y --no-install-recommends $1 > /dev/null
}
function _apt_available() {
    if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then
        echo "Package is available : $1"
        PACKAGE_INSTALL="1"
    else
        echo "Package $1 is NOT available for install"
        echo  "We can not continue without this package..."
        echo  "Exitting now.."
        exit 0
    fi
}
function _package_install {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install $1
            sleep 0.5
        fi
    fi
}

function _package_install_no_recommends {
    _apt_available $1
    if [ "${PACKAGE_INSTALL}" = "1" ]; then
        if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
             echo  "package is already_installed: $1"
        else
            echo  "installing package : $1, please wait.."
            _apt_install_norecommends $1
            sleep 0.5
        fi
    fi
}

1

यदि आप लोग / लड़कियों को काम करने के लिए यहाँ उत्तर नहीं दे सकते हैं और आपकी पीठ के बाल खींच रहे हैं, तो उसी कमांड का उपयोग करके चलाने का प्रयास करें bash -c। बस इस सोनामबुलर डेलिरियम को देखें। यह वास्तव में तब होता है जब आप $ (उप-कमांड) चलाते हैं:

प्रथम। यह आपको पूरी तरह से अलग आउटपुट दे सकता है।

$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls

दूसरा। यह आपको कोई आउटपुट नहीं दे सकता है।

$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found

अंतर शेल के इंटरैक्टिव और गैर-इंटरैक्टिव मोड के बीच अंतर के कारण होता है। आपका ~ / .bashrc केवल तभी पढ़ा जाता है जब शेल नॉन-लॉगिन और इंटरेक्टिव हो। हालांकि दूसरा अजीब लगता है, क्योंकि यह PATH पर्यावरण चर में अंतर के कारण होना चाहिए, लेकिन उपधारा पर्यावरण को विरासत में मिला है।
पालिक

मेरे मामले में .bashrcएक राशि [ -z "$PS1" ] && returnसे prepended # If not running interactively, don't do anythingइसलिए मुझे लगता है कि है कि एक कारण है कि गैर-सहभागी मोड में bashrc का भी स्पष्ट सोर्सिंग में मदद नहीं करता है। किसी स्क्रिप्ट को ss64.com/bash/source.html डॉट ऑपरेटर के साथ कॉल करके समस्या को हल किया जा सकता है, . ./script.shलेकिन यह वह चीज नहीं है जिसे हर बार टाइप करना याद रखना चाहिए।
user619271

1
सोर्सिंग स्क्रिप्ट जिन्हें खट्टा नहीं माना जाता है, एक बुरा विचार है। मैं बस यही कहना चाह रहा था कि आपके जवाब का थोड़ा बहुत सवाल है और बाश और उसके (गैर) इंटरेक्टिव मोड के साथ क्या करना है।
पालक

यदि यह बताया गया कि इन मामलों में क्या चल रहा है, तो यह एक उत्तर के लिए एक सहायक परिशिष्ट होगा।
16

1

यह स्थान के अनुसार बताएगा कि कार्यक्रम मौजूद है या नहीं:

    if [ -x /usr/bin/yum ]; then
        echo "This is Centos"
    fi

हाँ, मैंने इस कमांड को जोड़ा अगर आपको sevrer, Open suse, centos, डेबियन में एक पैकेज स्थापित करने की आवश्यकता है
Klevin Kona

"इको" लाइन में सिंटैक्स हाइलाइटिंग बंद है। उपाय क्या है? क्या यह सुझाव देता है कि बैश स्क्रिप्ट अलग होनी चाहिए?
पीटर मोर्टेंसन

@PeterMortensen सिंटैक्स हाइलाइटिंग बंद है क्योंकि यह नहीं जानता कि यह एक स्ट्रिंग है।
एड्रियन

0

हैश-वेरिएंट में एक नुकसान है: कमांड लाइन पर आप उदाहरण के लिए टाइप कर सकते हैं

one_folder/process

प्रक्रिया निष्पादित करने के लिए। इसके लिए one_folder का मूल फ़ोल्डर $ PATH में होना चाहिए । लेकिन जब आप इस कमांड को हैश करने की कोशिश करेंगे, तो यह हमेशा सफल होगा:

hash one_folder/process; echo $? # will always output '0'

4
"इसके लिए one_folder का मूल फ़ोल्डर होना चाहिए $PATH" - यह पूरी तरह से गलत है। कोशिश करो। इस कार्य के लिए, one_folder वर्तमान निर्देशिका में होना चाहिए ।
वाइल्डकार्ड

0

मैं "कमांड -v" का दूसरा उपयोग करता हूं। इस तरह:

md=$(command -v mkdirhier) ; alias md=${md:=mkdir}  # bash

emacs="$(command -v emacs) -nw" || emacs=nano
alias e=$emacs
[[ -z $(command -v jed) ]] && alias jed=$emacs

0

मुझे यह जांचना था कि क्या हमारे सीआई सर्वर को तैनात करने के हिस्से के रूप में गिट स्थापित किया गया था । मेरी अंतिम बैश स्क्रिप्ट इस प्रकार थी (उबंटू सर्वर):

if ! builtin type -p git &>/dev/null; then
  sudo apt-get -y install git-core
fi

3
सशर्त बल्कि बेकार है, उपयुक्त-चलने के लिए स्टार्टअप समय को मोड्यूलो करें, क्योंकि एप्टी-गेट संतुष्ट हो जाएगा और बाहर निकल जाएगा यदि गिट-कोर पहले से स्थापित है।
ट्रिपल

3
इसका स्टार्टअप समय नगण्य है, लेकिन अधिक महत्वपूर्ण प्रेरणा है sudo: सशर्त के बिना, यह हमेशा बंद रहेगा और पासवर्ड मांगेगा (जब तक कि आपने हाल ही में एक sudo नहीं किया था)। BTW, यह उपयोगी हो सकता है sudo -p "Type your password to install missing git-core: "ताकि शीघ्र नीले रंग से बाहर नहीं आता है।
बेनी चेर्नियाव्स्की-पास्किन

0

बैश की नकल करने के लिए type -P cmd, हम POSIX का उपयोग कर सकते हैं env -i type cmd 1>/dev/null 2>&1

man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.

ls() { echo 'Hello, world!'; }

ls
type ls
env -i type ls

cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }

7
इसे क्यों उखाड़ा जा रहा है? किन प्रणालियों पर यह वास्तव में आपके लिए काम करता है? typeएक प्रतीत हो रहा है builtinसबसे गोले में तो इस वजह से काम नहीं कर सकता envका उपयोग करता है execvpचलाने के लिए commandइतना commandनहीं एक हो सकता है builtin(और builtinहमेशा एक ही वातावरण में चलाया जाएगा)। यह मेरे लिए विफल रहता में bash, ksh93, zsh, busybox [a]shऔर dashजो सभी के प्रदान करते हैं typeएक खोल में निर्मित के रूप में।
एड्रियन फ्रुविर्थ

0

यदि कोई बाहरी typeआदेश उपलब्ध नहीं है (जैसा कि यहां दिया गया है ), हम POSIX का उपयोग कर सकते हैं env -i sh -c 'type cmd 1>/dev/null 2>&1':

# Portable version of Bash's type -P cmd (without output on stdout)
typep() {
   command -p env -i PATH="$PATH" sh -c '
      export LC_ALL=C LANG=C
      cmd="$1"
      cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
      [ $? != 0 ] && exit 1
      case "$cmd" in
        *\ /*) exit 0;;
            *) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
      esac
   ' _ "$1" || exit 1
}

# Get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp

कम से कम पर मैक ओएस एक्स v10.6.8 (स्नो लेपर्ड) बैश 4.2.24 (2) का उपयोग करने से command -v lsस्थानांतरित नहीं होता है /bin/ls-temp


0

यदि आप यह देखना चाहते हैं कि क्या कोई प्रोग्राम मौजूद है और वास्तव में एक प्रोग्राम है, तो बैश बिल्ट-इन कमांड नहीं , तब command, typeऔरhash परीक्षण के लिए उपयुक्त नहीं है क्योंकि वे सभी अंतर्निहित कमांड के लिए 0 एग्जिट स्टेटस लौटाते हैं।

उदाहरण के लिए, वहाँ समय प्रोग्राम है जो अन्य प्रस्ताव की तुलना में सुविधाओं समय में निर्मित आदेश। यह देखने के लिए कि क्या कार्यक्रम मौजूद है, मैं whichनिम्नलिखित उदाहरण में उपयोग करने का सुझाव दूंगा:

# First check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
  echo "The time program does not exist on this system."
  exit 1
fi

# Invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt

-1

लिपि

#!/bin/bash

# Commands found in the hash table are checked for existence before being
# executed and non-existence forces a normal PATH search.
shopt -s checkhash

function exists() {
 local mycomm=$1; shift || return 1

 hash $mycomm 2>/dev/null || \
 printf "\xe2\x9c\x98 [ABRT]: $mycomm: command does not exist\n"; return 1;
}
readonly -f exists

exists notacmd
exists bash
hash
bash -c 'printf "Fin.\n"'

परिणाम

 [ABRT]: notacmd: command does not exist
hits    command
   0    /usr/bin/bash
Fin.

-1

मैं इसका उपयोग करता हूं, क्योंकि यह बहुत आसान है:

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then echo exists;else echo "not exists";fi

या

if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then
echo exists
else echo "not exists"
fi

इसमें शेल बिल्डिंस और प्रोग्राम्स की इको स्टेटस से लेकर स्टैंडर्ड आउटपुट और स्टैंडर्ड एरर तक कुछ नहीं होता है। दूसरी ओर, यदि कोई कमांड नहीं मिली है, तो यह केवल मानक त्रुटि के लिए ईकोस स्थिति है।


-1

यह मानते हुए कि आप पहले से ही सुरक्षित शेल प्रथाओं का पालन कर रहे हैं :

set -eu -o pipefail
shopt -s failglob

./dummy --version 2>&1 >/dev/null

यह मानता है कि कमांड को इस तरह से लागू किया जा सकता है कि यह (लगभग) कुछ भी नहीं करता है, जैसे इसके संस्करण की रिपोर्ट करना या मदद दिखाना।

यदि dummyआदेश नहीं मिला है, तो बैश निम्नलिखित त्रुटि के साथ बाहर निकलता है ...

./my-script: line 8: dummy: command not found

यह अन्य command -v(और समान) उत्तरों की तुलना में अधिक उपयोगी और कम क्रिया है क्योंकि त्रुटि संदेश स्वतः उत्पन्न होता है और इसमें एक प्रासंगिक पंक्ति संख्या भी होती है।


यह उत्तर उन लोगों के लिए बहुत स्पष्ट नहीं है जो शेल के साथ अच्छे नहीं हैं क्योंकि यह नहीं बताता है कि इस कोड का उपयोग कैसे किया जाना चाहिए और यह कई अन्य उत्तरों से अलग है कि परीक्षण के असफल शाखा के dummyअस्तित्व के हाथों से बाहर है स्क्रिप्ट के लेखक। इसके अलावा, इसमें इस बात की व्याख्या नहीं है कि यह कैसे काम करता है और यह निष्पादन पर्यावरण की सेटिंग्स को बदलता है।
पैलेक

यह एक बैश प्रश्न है, लेकिन यह ध्यान देने योग्य है कि गैर-पॉसिक्स shoptकॉल को पॉसिक्स के साथ बदल दिया जा सकता है set -f, जो छोटा और पोर्टेबल है। Pipefail विकल्प POSIX में समर्थित नहीं है , हालांकि, और कोई विकल्प, AFAIK है।
पालेक

@Palec मुझे यकीन नहीं है कि यह कैसे मुश्किल है। यह वास्तव में सरल है क्योंकि यह शेल पर निर्भर करता है ताकि उपयोगकर्ता को यह पता चल सके कि कमांड नहीं मिल सकता है और एक त्रुटि के साथ बाहर निकलता है, जैसा कि ओपी द्वारा अनुरोध किया गया है। मुझे पता है कि मैं क्या याद किया :)
Adrien
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.