मैं कैसे पुष्टि करूंगा कि एक कार्यक्रम मौजूद है, एक तरह से जो या तो एक त्रुटि और निकास लौटेगा, या स्क्रिप्ट के साथ जारी रहेगा?
ऐसा लगता है कि यह आसान होना चाहिए, लेकिन यह मुझे स्टम्पिंग कर रहा है।
मैं कैसे पुष्टि करूंगा कि एक कार्यक्रम मौजूद है, एक तरह से जो या तो एक त्रुटि और निकास लौटेगा, या स्क्रिप्ट के साथ जारी रहेगा?
ऐसा लगता है कि यह आसान होना चाहिए, लेकिन यह मुझे स्टम्पिंग कर रहा है।
जवाबों:
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
अभी तक इसे नहीं देखा है)। command
POSIX द्वारा बाहर निकलने की स्थिति को अच्छी तरह से परिभाषित किया गया है, ताकि कोई संभवतः उपयोग करने के लिए सबसे सुरक्षित हो।
अपनी स्क्रिप्ट का उपयोग करता है, तो bash
हालांकि, POSIX नियम वास्तव में बात अब और नहीं है और दोनों type
और hash
पूरी तरह से उपयोग करने के लिए सुरक्षित हो जाते हैं। type
अब एक है -P
खोजने के लिए बस PATH
औरhash
इसका साइड-इफेक्ट है कि कमांड का स्थान हैशेड हो जाएगा (अगली बार जब आप इसे उपयोग करते हैं तो तेजी से देखने के लिए), जो आमतौर पर एक अच्छी बात है क्योंकि आप वास्तव में इसका उपयोग करने के लिए इसके अस्तित्व की जांच करते हैं। ।
एक सरल उदाहरण के रूप में, यहां एक फ़ंक्शन है जो gdate
अगर मौजूद है, तो चलता है date
:
gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}
2>&-
("क्लोज़ आउटपुट फ़ाइल डिस्क्रिप्टर 2", जो कि stderr है) के समान परिणाम है 2> /dev/null
; 2) >&2
एक शॉर्टकट है 1>&2
, जिसे आप "रेडर स्टडआउट टू स्टडर" के रूप में पहचान सकते हैं। देखें उन्नत बैश पटकथा गाइड आई / ओ पुनर्निर्देशन पेज अधिक जानकारी के लिए।
while read element ; do .. done <<< $(echo ${ArrayVar[*]})
, for word in $(fgrep -l $ORIGINAL *.txt)
, ls -l "$directory" | sed 1d
, {{के लिए एक में seq $BEGIN $END
}} ... कई लेखकों से संपर्क करें और सुधार का प्रस्ताव करने की कोशिश की है, लेकिन यह कोई विकी है और अनुरोध बहरा कान पर पहुँचे हैं।
2>&-
जैसा नहीं है 2>/dev/null
। पूर्व फ़ाइल डिस्क्रिप्टर को बंद कर देता है, जबकि बाद वाला इसे केवल रीडायरेक्ट करता है /dev/null
। आपको कोई त्रुटि दिखाई नहीं दे सकती क्योंकि प्रोग्राम आपको stderr पर सूचित करने का प्रयास करता है कि stderr बंद है।
यह जाँचने का एक पोर्टेबल तरीका है कि क्या कोई कमांड मौजूद है $PATH
और निष्पादन योग्य है:
[ -x "$(command -v foo)" ]
उदाहरण:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
निष्पादन योग्य चेक की आवश्यकता है क्योंकि बैश एक गैर-निष्पादन योग्य फ़ाइल देता है यदि उस नाम के साथ कोई निष्पादन योग्य फ़ाइल नहीं मिलती है $PATH
।
यह भी ध्यान दें कि यदि निष्पादन योग्य नाम के साथ एक गैर-निष्पादन योग्य फ़ाइल पहले से मौजूद है $PATH
, तो डैश पूर्व को वापस कर देता है, भले ही बाद में निष्पादित किया जाएगा। यह एक बग है और POSIX मानक के उल्लंघन में है। [ बग रिपोर्ट ] [ मानक ]
इसके अलावा, यह विफल हो जाएगा यदि आप जिस कमांड की तलाश कर रहे हैं उसे एक उपनाम के रूप में परिभाषित किया गया है।
command -v
एक गैर-निष्पादन योग्य फ़ाइल के लिए भी एक पथ का उत्पादन करेगा ? यही है, -x वास्तव में आवश्यक है?
-x
परीक्षण करता है कि फ़ाइल निष्पादन योग्य है, जो कि प्रश्न था।
command
खुद इसके निष्पादन योग्य होने के लिए परीक्षण करेगा - क्या यह नहीं होगा?
$PATH
जब कोई कमांड निष्पादित करता है तो डैश, बैश और zsh सभी गैर-निष्पादन योग्य फ़ाइलों को छोड़ देते हैं । हालाँकि, का व्यवहार command -v
बहुत असंगत है। डैश में, यह $PATH
निष्पादन योग्य पहली फ़ाइल देता है , भले ही यह निष्पादन योग्य हो या नहीं। बैश में, यह पहला निष्पादन योग्य मैच देता है $PATH
, लेकिन यदि कोई नहीं है, तो यह एक गैर-निष्पादन योग्य फ़ाइल लौटा सकता है। और zsh में, यह एक गैर-निष्पादन योग्य फ़ाइल कभी नहीं लौटाएगा।
dash
उन तीनों में से केवल एक ही है जो गैर-पॉसिक्स-आज्ञाकारी है; [ -x "$(command -v COMMANDNAME)"]
अन्य दो में काम करेंगे। ऐसा लगता है कि यह बग पहले ही रिपोर्ट किया जा चुका है, लेकिन अभी तक कोई प्रतिक्रिया नहीं मिली है: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
मैं लूनाथ से सहमत हूं कि वे इसके उपयोग को हतोत्साहित करें which
और बश उपयोगकर्ताओं के लिए उसका समाधान पूरी तरह से मान्य है । हालाँकि, अधिक पोर्टेबल command -v
होने के बजाय , इसका उपयोग किया जाएगा:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
कमांड command
POSIX अनुपालन है। इसके विनिर्देशन के लिए यहां देखें: कमांड - एक साधारण कमांड निष्पादित करें
नोट: type
POSIX शिकायत है, लेकिन type -P
नहीं है।
exit 1;
एक xterm को मारता है, अगर वहां से आह्वान किया जाता है।
&>/dev/null
। हालाँकि, मैं आपसे सहमत हूँ, जो वास्तव में मायने रखता है, वह है पोर्टेबिलिटी, मैंने अपने उत्तर को उसी हिसाब से संपादित किया है, अब मानक sh पुनर्निर्देशन का उपयोग कर रहा हूँ >/dev/null 2>&1
।
मेरे पास मेरे .bashrc में एक फ़ंक्शन परिभाषित है जो इसे आसान बनाता है।
command_exists () {
type "$1" &> /dev/null ;
}
इसका उपयोग कैसे किया जाता है (मेरे .bash_profile
)
if command_exists mvim ; then
export VISUAL="mvim --nofork"
fi
&>
है?
&>
दोनों stdout और stderr पुनर्निर्देश एक साथ।
&>
आपके बैश के संस्करण में उपलब्ध नहीं हो सकता है। मार्सेलो का कोड ठीक काम करना चाहिए; यह वही काम करता है।
then
उदाहरण के लिए इस शब्द के साथ प्रयास करें । यदि आपको निष्पादन योग्य होने की आवश्यकता है तो इस उत्तर को देखें $PATH
।
यह इस बात पर निर्भर करता है कि आप यह जानना चाहते हैं कि क्या यह $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
कार्यक्रम के आउटपुट को दबा देता है ।
@ 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
command
उपनाम के लिए भी सफल होता है, जो कुछ हद तक प्रतिवाद हो सकता है। एक इंटरैक्टिव शेल में अस्तित्व के लिए जाँच करने से अलग-अलग परिणाम मिलेंगे जब आप इसे किसी स्क्रिप्ट में स्थानांतरित करेंगे।
shopt -u expand_aliases
अलिज़र्स / हाइड्स (जैसे alias ls='ls -F'
किसी अन्य उत्तर में उल्लिखित) का उपयोग करके परीक्षण किया है और shopt -s expand_aliases
उनके माध्यम से हल करता है command -v
। तो शायद यह चेक से पहले सेट किया जाना चाहिए और बाद में परेशान होना चाहिए, हालांकि यह फ़ंक्शन रिटर्न मान को प्रभावित कर सकता है यदि आप कैप्चर नहीं करते हैं और कमांड कॉल का आउटपुट स्पष्ट रूप से वापस करते हैं।
प्रयोग करके देखें:
test -x filename
या
[ -x filename ]
सशर्त अभिव्यक्तियों के तहत बैश मैनपेज से :
-x file True if file exists and is executable.
का उपयोग करने के लिए 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
मानक त्रुटि पर संदेश लिखता है।
if hash foo &> /dev/null; then ...
?
मुझे उस बॉक्स पर काम करने के लिए पिछले उत्तर कभी नहीं मिले जिनकी मुझे पहुँच है। एक के लिए, type
स्थापित किया गया है (क्या more
करता है)। इसलिए बिल्टइन डायरेक्शन की जरूरत है। यह कमांड मेरे लिए काम करती है:
if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
if
सिंटैक्स का हिस्सा नहीं है , बस उपयोग करें if builtin type -p vim; then ...
। और backticks वास्तव में प्राचीन और पदावनत सिंटैक्स हैं, सभी आधुनिक प्रणालियों $()
द्वारा भी समर्थित sh
हैं।
कई निर्भरता के लिए जाँच करें और उपयोगकर्ताओं को समाप्त करने के लिए स्थिति को सूचित करें
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 संकुल स्थापित है और यदि लिनक्स पर नहीं है तो इसे स्थापित करें
यह पहले उल्लेख किया गया था: मैं कैसे जांच कर सकता हूं कि क्या कोई प्रोग्राम बैश स्क्रिप्ट से मौजूद है?
column -t
(उपयोग-लिनेक्स का हिस्सा)।
यदि आप प्रोग्राम के अस्तित्व की जाँच करते हैं, तो आप शायद इसे बाद में चलाने जा रहे हैं। इसे पहली जगह में चलाने की कोशिश क्यों नहीं की गई?
if foo --version >/dev/null 2>&1; then
echo Found
else
echo Not found
fi
यह एक अधिक विश्वसनीय जांच है कि कार्यक्रम केवल पीएटीएच निर्देशिकाओं और फ़ाइल अनुमतियों को देखने से चलता है।
साथ ही आप अपने प्रोग्राम से कुछ उपयोगी परिणाम प्राप्त कर सकते हैं, जैसे कि इसका संस्करण।
बेशक कमियां यह हैं कि कुछ कार्यक्रम शुरू करने के लिए भारी पड़ सकते हैं और कुछ में --version
तुरंत (और सफलतापूर्वक) बाहर निकलने का विकल्प नहीं है ।
hash foo 2>/dev/null
: Z शेल (Zsh), बैश, डैश और ऐश के साथ काम करता है ।
type -p foo
: यह Z शेल, बैश और ऐश ( बिज़ीबॉक्स ) के साथ काम करता प्रतीत होता है , लेकिन डैश नहीं (यह -p
एक तर्क के रूप में व्याख्या करता है)।
command -v foo
: Z शेल, बैश, डैश के साथ काम करता है, लेकिन ऐश (बिजीबॉक्स) ( -ash: command: not found
) नहीं।
यह भी ध्यान दें कि builtin
राख और डैश के साथ उपलब्ध नहीं है।
यदि आप कर सकते हैं तो बाश बिल्डरों का उपयोग करें:
which programname
...
type -P programname
which
बैश बिलियन नहीं है।
-P
पॉसिक्स नहीं है। क्यों type -P
पसंद किया जाता है?
-v
यदि POSIX_BUILTINS विकल्प सेट है, तो कमांड ठीक काम करती है<command>
को जांचने के लिए , लेकिन यह विफल हो सकता है यदि नहीं। (इसने मेरे लिए वर्षों तक काम किया है, लेकिन मैं हाल ही में एक में भाग गया जहां यह काम नहीं किया।)
मुझे लगता है कि निम्नलिखित अधिक विफल हो जाएगा:
test -x $(which <command>)
चूंकि यह तीन चीजों के लिए परीक्षण करता है: पथ, अस्तित्व और निष्पादन की अनुमति।
test -x $(which ls)
रिटर्न 0, करता है test -x $(which sudo)
, भले ही ls
स्थापित किया गया है और runnable और sudo
भी डोकर कंटेनर मैं में चल रहा हूँ के भीतर स्थापित नहीं है।
test -x "$(which <command>)"
ls
है? मुझे नहीं लगता कि अगर कमांड में पैरामीटर है तो यह काम करेगा।
रुचि रखने वालों के लिए, पिछले उत्तरों में कोई भी कार्यप्रणाली काम नहीं करती है यदि आप एक स्थापित पुस्तकालय का पता लगाना चाहते हैं। मैं कल्पना करता हूं कि आप या तो शारीरिक रूप से पथ की जांच कर रहे हैं (हेडर फ़ाइलों और इस तरह के लिए), या ऐसा कुछ (यदि आप डेबियन-आधारित वितरण पर हैं):
dpkg --status libdb-dev | grep -q not-installed
if [ $? -eq 0 ]; then
apt-get install libdb-dev
fi
जैसा कि आप ऊपर से देख सकते हैं, क्वेरी से "0" उत्तर का मतलब पैकेज स्थापित नहीं है। यह "grep" का एक फ़ंक्शन है - एक "0" का अर्थ है एक मैच पाया गया था, एक "1" का मतलब है कि कोई मैच नहीं मिला।
cmd; if [ $? -eq 0 ]; then
को if cmd; then
dpkg
या के माध्यम से स्थापित करने के लिए काम करता हैapt
यहां विकल्पों में से एक टन है, लेकिन मुझे आश्चर्य नहीं हुआ कि कोई भी एक-लाइनर नहीं था। यह वही है जो मैंने अपनी लिपियों की शुरुआत में इस्तेमाल किया था:
[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }
यह यहां चयनित उत्तर और एक अन्य स्रोत पर आधारित है।
मैं कहूँगा कि किसी भी पोर्टेबल और 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 }
shopt -u expand_aliases
इन एलियनों को इग्नोर किया / छुपाया और इनका प्रयोग करके shopt -s expand_aliases
दिखाया command -v
।
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
चलाया जाता है - यह कुछ समस्याओं को बचाता है ...
डेबियन सर्वर के लिए मेरा सेटअप :
मुझे समस्या तब हुई जब कई पैकेजों में एक ही नाम था।
उदाहरण के लिए 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
}
यदि आप लोग / लड़कियों को काम करने के लिए यहाँ उत्तर नहीं दे सकते हैं और आपकी पीठ के बाल खींच रहे हैं, तो उसी कमांड का उपयोग करके चलाने का प्रयास करें 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
एक राशि [ -z "$PS1" ] && return
से prepended # If not running interactively, don't do anything
इसलिए मुझे लगता है कि है कि एक कारण है कि गैर-सहभागी मोड में bashrc का भी स्पष्ट सोर्सिंग में मदद नहीं करता है। किसी स्क्रिप्ट को ss64.com/bash/source.html डॉट ऑपरेटर के साथ कॉल करके समस्या को हल किया जा सकता है, . ./script.sh
लेकिन यह वह चीज नहीं है जिसे हर बार टाइप करना याद रखना चाहिए।
यह स्थान के अनुसार बताएगा कि कार्यक्रम मौजूद है या नहीं:
if [ -x /usr/bin/yum ]; then
echo "This is Centos"
fi
हैश-वेरिएंट में एक नुकसान है: कमांड लाइन पर आप उदाहरण के लिए टाइप कर सकते हैं
one_folder/process
प्रक्रिया निष्पादित करने के लिए। इसके लिए one_folder का मूल फ़ोल्डर $ PATH में होना चाहिए । लेकिन जब आप इस कमांड को हैश करने की कोशिश करेंगे, तो यह हमेशा सफल होगा:
hash one_folder/process; echo $? # will always output '0'
$PATH
" - यह पूरी तरह से गलत है। कोशिश करो। इस कार्य के लिए, one_folder वर्तमान निर्देशिका में होना चाहिए ।
मैं "कमांड -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
मुझे यह जांचना था कि क्या हमारे सीआई सर्वर को तैनात करने के हिस्से के रूप में गिट स्थापित किया गया था । मेरी अंतिम बैश स्क्रिप्ट इस प्रकार थी (उबंटू सर्वर):
if ! builtin type -p git &>/dev/null; then
sudo apt-get -y install git-core
fi
sudo
: सशर्त के बिना, यह हमेशा बंद रहेगा और पासवर्ड मांगेगा (जब तक कि आपने हाल ही में एक sudo नहीं किया था)। BTW, यह उपयोगी हो सकता है sudo -p "Type your password to install missing git-core: "
ताकि शीघ्र नीले रंग से बाहर नहीं आता है।
बैश की नकल करने के लिए 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; }
type
एक प्रतीत हो रहा है builtin
सबसे गोले में तो इस वजह से काम नहीं कर सकता env
का उपयोग करता है execvp
चलाने के लिए command
इतना command
नहीं एक हो सकता है builtin
(और builtin
हमेशा एक ही वातावरण में चलाया जाएगा)। यह मेरे लिए विफल रहता में bash
, ksh93
, zsh
, busybox [a]sh
और dash
जो सभी के प्रदान करते हैं type
एक खोल में निर्मित के रूप में।
यदि कोई बाहरी 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
।
यदि आप यह देखना चाहते हैं कि क्या कोई प्रोग्राम मौजूद है और वास्तव में एक प्रोग्राम है, तो बैश बिल्ट-इन कमांड नहीं , तब 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
लिपि
#!/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.
मैं इसका उपयोग करता हूं, क्योंकि यह बहुत आसान है:
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
इसमें शेल बिल्डिंस और प्रोग्राम्स की इको स्टेटस से लेकर स्टैंडर्ड आउटपुट और स्टैंडर्ड एरर तक कुछ नहीं होता है। दूसरी ओर, यदि कोई कमांड नहीं मिली है, तो यह केवल मानक त्रुटि के लिए ईकोस स्थिति है।
यह मानते हुए कि आप पहले से ही सुरक्षित शेल प्रथाओं का पालन कर रहे हैं :
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 है।
which
इनके लिए सही है।type
बिना तर्कों के अतिरिक्त आरक्षित शब्दों और शेल बिल्डरों के लिए सही वापसी होगी। यदि "प्रोग्राम" का अर्थ है "बहने योग्य$PATH
", तो यह उत्तर देखें ।