यहाँ आप कभी नहीं सोचा था कि आप इसके बारे में जानना कभी नहीं चाहेंगे:
सारांश
बॉर्न जैसी शेल स्क्रिप्ट में एक निष्पादन योग्य का पथनाम प्राप्त करने के लिए (कुछ कैविएट हैं; नीचे देखें):
ls=$(command -v ls)
यह जानने के लिए कि क्या कोई दिया गया आदेश मौजूद है:
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
एक इंटरैक्टिव बॉर्न की तरह खोल के संकेत पर:
type ls
which
आदेश सी-शैल से एक टूटी हुई विरासत है और बेहतर बॉर्न की तरह गोले में अकेला छोड़ दिया जाता है।
बक्सों का इस्तेमाल करें
एक स्क्रिप्ट के भाग के रूप में या शैल प्रांप्ट पर अंतःक्रियात्मक रूप से उस जानकारी की तलाश करने में अंतर है।
शेल प्रॉम्प्ट में, विशिष्ट उपयोग मामला है: यह कमांड अजीब तरह से व्यवहार करता है, क्या मैं सही का उपयोग कर रहा हूं? जब मैंने टाइप किया तो वास्तव में क्या हुआ mycmd
? क्या मैं आगे देख सकता हूं कि यह क्या है?
उस स्थिति में, आप यह जानना चाहते हैं कि जब आप कमांड को वास्तव में कमांड को लागू किए बिना अपना शेल क्या करते हैं।
शेल स्क्रिप्ट में, यह काफी अलग है। शेल स्क्रिप्ट में कोई कारण नहीं है कि आप यह जानना चाहते हैं कि यदि आप क्या करना चाहते हैं तो यह कहां या क्या है, तो इसे चलाएं। आम तौर पर, आप जो जानना चाहते हैं, वह निष्पादन योग्य का मार्ग है, इसलिए आप इससे अधिक जानकारी प्राप्त कर सकते हैं (जैसे उस के सापेक्ष किसी अन्य फ़ाइल का पथ, या उस पथ पर निष्पादन योग्य फ़ाइल की सामग्री से जानकारी पढ़ें)।
सहभागितापूर्ण तरीके से, आप के बारे में पता करने के लिए चाहते हो सकता है सभीmy-cmd
आदेशों सिस्टम पर उपलब्ध, लिपियों में, शायद ही कभी इतना।
उपलब्ध उपकरणों में से अधिकांश (जैसा कि अक्सर होता है) को अंतःक्रियात्मक रूप से उपयोग करने के लिए डिज़ाइन किया गया है।
इतिहास
पहले थोड़ा इतिहास।
70 के दशक के उत्तरार्ध तक शुरुआती यूनिक्स गोले का कोई कार्य या उपनाम नहीं था। केवल निष्पादन में पारंपरिक देख रहे हैं $PATH
। csh
1978 के आसपास उपनामों को पेश किया (हालांकि मई 1979 में csh
पहली बार जारी किया गया था 2BSD
), और .cshrc
शेल (हर शेल को अनुकूलित करने के लिए उपयोगकर्ताओं के लिए प्रसंस्करण भी , जैसा कि स्क्रिप्ट में इंटरएक्टिव नहीं होने पर भी csh
पढ़ता है .cshrc
)।
जबकि बॉर्न शेल पहली बार 1979 में यूनिक्स वी 7 में जारी किया गया था, फ़ंक्शन समर्थन केवल बहुत बाद में (एसवीआर 2 में 1984) जोड़ा गया था, और वैसे भी, इसमें कभी भी कुछ rc
फ़ाइल नहीं थी ( .profile
आपके पर्यावरण को कॉन्फ़िगर करने के लिए, शेल प्रति नहीं )।
csh
बॉर्न शेल की तुलना में बहुत अधिक लोकप्रिय हो गया (हालांकि इसमें बॉर्न शेल की तुलना में एक बहुत बुरा सिंटैक्स था) यह इंटरैक्टिव उपयोग के लिए बहुत अधिक सुविधाजनक और अच्छी सुविधाओं को जोड़ रहा था।
में 3BSD
(1980), एक which
csh स्क्रिप्ट के लिए जोड़ा गया है csh
उन एक निष्पादन की पहचान में मदद करने के लिए, और यह एक मुश्किल से भिन्न स्क्रिप्ट आप के रूप में मिल सकता है which
कई वाणिज्यिक Unices आजकल (Salaris, HP / UX, AIX या Tru64 की तरह) पर।
वह स्क्रिप्ट उपयोगकर्ता को पढ़ता है ~/.cshrc
(जैसे कि सभी csh
स्क्रिप्ट तब तक लागू नहीं होती हैं csh -f
), और एलियासेस की सूची में दिए गए कमांड नाम (ओं) और $path
(जो सरणी के csh
आधार पर बनाए रखता है $PATH
) को देखता है ।
यहाँ आप जाते हैं, which
उस समय सबसे लोकप्रिय शेल के लिए पहली बार आया csh
था (और 90 के दशक के मध्य तक अभी भी लोकप्रिय था), जो मुख्य कारण है कि यह पुस्तकों में प्रलेखित हुआ और अभी भी व्यापक रूप से उपयोग किया जाता है।
ध्यान दें, यहां तक कि एक csh
उपयोगकर्ता के लिए, वह which
csh स्क्रिप्ट जरूरी नहीं कि आपको सही जानकारी दे। इसे एलियन्स में परिभाषित किया गया है ~/.cshrc
, न कि जिन्हें आपने बाद में प्रॉम्प्ट या उदाहरण के लिए source
किसी अन्य csh
फ़ाइल के द्वारा परिभाषित किया है , और (हालांकि यह एक अच्छा विचार नहीं होगा), PATH
को फिर से परिभाषित किया जा सकता है ~/.cshrc
।
which
बॉर्न शेल से उस कमांड को चलाना , अभी भी आपके में परिभाषित उपनामों को खोजेगा ~/.cshrc
, लेकिन अगर आपके पास कोई नहीं है क्योंकि आप उपयोग नहीं करते हैं csh
, तब भी शायद आपको सही उत्तर मिलेगा।
बिलियन type
कमांड के साथ SVR2 में 1984 तक बॉर्न शेल में एक समान कार्यक्षमता नहीं जोड़ी गई थी । तथ्य यह है कि यह builtin है (किसी बाहरी स्क्रिप्ट के विपरीत) मतलब है कि यह कर सकते हैं कि आप सही जानकारी (कुछ हद तक) देने के रूप में यह खोल के आंतरिक भागों तक पहुँच गया है।
प्रारंभिक type
कमांड एक समान समस्या से ग्रस्त थी क्योंकि which
स्क्रिप्ट में यह विफलता विफलता की स्थिति नहीं लौटाती थी यदि कमांड नहीं मिली थी। इसके अलावा, निष्पादन के लिए, इसके विपरीत which
, यह कुछ के ls is /bin/ls
बजाय सिर्फ /bin/ls
स्क्रिप्ट में उपयोग करने के लिए आसान बना दिया है जो कुछ की तरह उत्पादन ।
यूनिक्स संस्करण 8 का (जंगली में जारी नहीं किया गया) बॉर्न शेल का type
नाम बदलकर बनाया गया था whatis
। और Plan9 (यूनिक्स के उत्तराधिकारी एक बार होने वाली है) खोल rc
(और इस तरह अपने डेरिवेटिव akanga
और es
) है whatis
और साथ ही।
कोर्न शेल (जिसका एक उपसमूह POSIX sh परिभाषा पर आधारित है), 80 के दशक के मध्य में विकसित हुआ, लेकिन 1988 से पहले व्यापक रूप से उपलब्ध नहीं था, csh
बॉर्न शेल के शीर्ष पर कई विशेषताएं (लाइन संपादक, उपनाम ...) जोड़ी गईं। । इसने अपने स्वयं के whence
बिलिन (इसके अलावा type
) को जोड़ा, जो कई विकल्पों को ले गया ( जैसे-वर्बोज़ आउटपुट के -v
साथ प्रदान करने के लिए type
, और -p
केवल निष्पादन योग्य के लिए देखने के लिए (उपनाम / फ़ंक्शन नहीं ...)।
एटी एंड टी और बर्कले के बीच कॉपीराइट मुद्दों के संबंध में उथल-पुथल के संयोग से, कुछ मुफ्त सॉफ्टवेयर शेल कार्यान्वयन 80 के दशक के उत्तरार्ध में 90 के दशक की शुरुआत में सामने आए। सभी अल्मक्विस्ट शेल (राख, BSDs में बॉर्न शेल के प्रतिस्थापन के लिए), ksh (pdksh), bash
(FSF द्वारा प्रायोजित ) का सार्वजनिक डोमेन कार्यान्वयन , zsh
1989 और 1991 के बीच में आया।
हालांकि, ऐश का मतलब बॉर्न शेल के लिए एक प्रतिस्थापन था, हालांकि type
बाद में (नेटबीएसडी 1.3 और फ्रीबीएसडी 2.3 में) एक बिलिन नहीं था , हालांकि यह था hash -v
। OSF / 1 /bin/sh
में एक type
बिल्डिन था जो हमेशा OSF / 1 v3.x तक 0 लौटाता था। पथ प्रिंट करने के लिए एक विकल्प bash
नहीं whence
जोड़ा गया ( जैसा होगा ) और सभी मिलान आदेशों को रिपोर्ट करने के लिए। बनाया निर्मित और एक जोड़ा आदेश की तरह कार्य कर रहा है । उन सभी को है।-p
type
type -p
whence -p
-a
tcsh
which
where
bash
type -a
zsh
fish
खोल (2005) एक है type
आदेश एक समारोह के रूप में लागू।
इस which
बीच csh स्क्रिप्ट को NetBSD से हटा दिया गया था (क्योंकि यह tcsh में बनाया गया था और अन्य गोले में ज्यादा इस्तेमाल नहीं किया गया था), और इसमें जो फंक्शनलिटी जोड़ी गई है whereis
(जब इनवॉइस किया जाता है which
, तो whereis
ऐसा व्यवहार करता है कि which
सिवाय इसके कि यह केवल एग्जीक्यूटिव दिखता है $PATH
)। OpenBSD और FreeBSD में, which
C में लिखे एक को भी बदल दिया गया जो $PATH
केवल कमांड में दिखता है ।
क्रियान्वयन
which
विभिन्न सिंटैक्स और व्यवहार के साथ विभिन्न यूनियनों पर एक कमांड के दर्जनों कार्यान्वयन हैं।
लिनक्स पर (बिल्टइन के बगल में tcsh
और zsh
) हम कई कार्यान्वयन पाते हैं। उदाहरण के लिए हाल ही में डेबियन सिस्टम पर, यह एक साधारण पोसिक्स शेल स्क्रिप्ट है जो कमांड में दिखता है $PATH
।
busybox
एक which
कमांड भी है ।
वहाँ एक है GNU
which
जो शायद सबसे असाधारण है। यह विस्तारित करने का प्रयास करता है कि which
csh स्क्रिप्ट ने अन्य गोले के लिए क्या किया है: आप इसे बता सकते हैं कि आपके उपनाम और कार्य क्या हैं ताकि यह आपको एक बेहतर उत्तर दे सके (और मेरा मानना है कि कुछ लिनक्स वितरणों ने इसके लिए कुछ वैश्विक उपनाम सेट किए हैं bash
) ।
zsh
निष्पादकों के मार्ग का विस्तार करने के लिए ऑपरेटरों के एक जोड़े हैं : =
फ़ाइल नाम विस्तार ऑपरेटर और :c
इतिहास विस्तार संशोधक (यहाँ पैरामीटर विस्तार पर लागू ):
$ print -r -- =ls
/bin/ls
$ cmd=ls; print -r -- $cmd:c
/bin/ls
zsh
, zsh/parameters
मॉड्यूल में commands
साहचर्य सारणी के रूप में कमांड हैश तालिका बनाता है :
$ print -r -- $commands[ls]
/bin/ls
whatis
उपयोगिता (यूनिक्स वी 8 बॉर्न शैल या योजना 9 में एक को छोड़कर rc
/ es
) वास्तव में संबंधित नहीं है यह केवल प्रलेखन के लिए के रूप में (whatis डेटाबेस greps, उस आदमी पेज सार 'है)।
whereis
को 3BSD
उसी समय में भी जोड़ा गया था, जैसा which
कि इसमें लिखा गया था C
, न csh
कि एक ही समय में देखने के लिए उपयोग किया जाता है, निष्पादन योग्य, मैन पेज और स्रोत लेकिन वर्तमान परिवेश पर आधारित नहीं है। तो फिर, कि एक अलग जरूरत का जवाब।
अब, मानक मोर्चे पर, POSIX command -v
और -V
कमांड निर्दिष्ट करता है (जो POSIX.2008 तक वैकल्पिक हुआ करता था)। UNIX type
कमांड निर्दिष्ट करता है (कोई विकल्प नहीं)। ऐसा इसलिए है सब ( where
, which
, whence
किसी भी मानक में निर्दिष्ट नहीं कर रहे हैं)
कुछ संस्करण तक, type
और command -v
लिनक्स स्टैंडर्ड बेस स्पेसिफिकेशन में वैकल्पिक थे , जो बताता है कि उदाहरण के लिए posh
(हालांकि pdksh
दोनों के आधार पर ) के कुछ पुराने संस्करण या तो नहीं थे। command -v
कुछ बॉर्न शेल कार्यान्वयन (जैसे सोलारिस पर) में भी जोड़ा गया था।
स्थिति आज
स्थिति आजकल वह यह है कि type
और command -v
सब बॉर्न की तरह गोले (हालांकि, के रूप में @jarno द्वारा बताया गया है, ध्यान दें में चेतावनी / बग में सर्वत्र हैं bash
जब POSIX मोड या Almquist के कुछ वंश में नहीं टिप्पणी में नीचे शैल)। tcsh
एकमात्र शेल है जहां आप उपयोग करना चाहेंगे which
(जैसा कि वहाँ नहीं type
है और which
बिलिन है)।
के अलावा अन्य के गोले में tcsh
और zsh
, which
आप जब तक वहाँ कोई अन्य नाम या समारोह है कि इसी नाम से हमारे में से किसी में है के रूप में दिया निष्पादन के पथ बता सकते हैं ~/.cshrc
, ~/.bashrc
या किसी खोल स्टार्टअप फ़ाइल और आप परिभाषित नहीं करते $PATH
अपने में ~/.cshrc
। यदि आपके पास इसके लिए एक उपनाम या फ़ंक्शन परिभाषित है, तो यह आपको इसके बारे में नहीं बता सकता है, या आपको गलत बात बता सकता है।
यदि आप किसी दिए गए नाम से सभी कमांड के बारे में जानना चाहते हैं, तो पोर्टेबल कुछ भी नहीं है। आप का उपयोग करेंगे where
में tcsh
या zsh
, type -a
में bash
या zsh
, whence -a
ksh93 में और अन्य गोले में, आप उपयोग कर सकते हैं type
संयोजन में साथ which -a
जो काम कर सकते हैं।
अनुशंसाएँ
एक निष्पादन योग्य के लिए पथनाम प्राप्त करना
अब, एक स्क्रिप्ट में एक निष्पादन योग्य का पथनाम प्राप्त करने के लिए, कुछ चेतावनी हैं:
ls=$(command -v ls)
यह करने का मानक तरीका होगा।
हालांकि कुछ मुद्दे हैं:
- इसे क्रियान्वित किए बिना निष्पादन योग्य का मार्ग जानना संभव नहीं है। सभी
type
, which
, command -v
... सभी उपयोग heuristics पथ पता लगाने के लिए। वे $PATH
घटकों के माध्यम से लूप करते हैं और पहली गैर-निर्देशिका फ़ाइल पाते हैं जिसके लिए आपने अनुमति दी है। हालाँकि, शेल के आधार पर, जब कमांड को निष्पादित करने की बात आती है, तो उनमें से कई (बॉर्न, एटी एंड टी केश, ज़श, ऐश ...) सिर्फ़ उन्हें $PATH
तब तक निष्पादित करेगा जब तक कि execve
सिस्टम कॉल एक त्रुटि के साथ वापस नहीं आता। । उदाहरण के लिए यदि $PATH
इसमें सम्मिलित है /foo:/bar
और आप निष्पादित करना चाहते हैं ls
, तो वे पहले निष्पादित करने का प्रयास करेंगे /foo/ls
या यदि वह विफल रहता है /bar/ls
। अब का निष्पादन/foo/ls
विफल हो सकता है क्योंकि आपके पास निष्पादन की अनुमति नहीं है, लेकिन कई अन्य कारणों से भी, जैसे कि यह एक वैध निष्पादन योग्य नहीं है। command -v ls
रिपोर्ट करेंगी /foo/ls
कि क्या आपके पास निष्पादन की अनुमति है /foo/ls
, लेकिन यदि ls
वास्तव में वैध निष्पादन योग्य नहीं है /bar/ls
तो चल सकता /foo/ls
है।
- अगर
foo
एक बिलिन या फ़ंक्शन या उपनाम है, तो command -v foo
रिटर्न foo
। जैसे कुछ गोले ash
, pdksh
या zsh
, यह भी वापस आ सकता है foo
यदि $PATH
खाली स्ट्रिंग शामिल है और foo
वर्तमान निर्देशिका में एक निष्पादन योग्य फ़ाइल है। ऐसी कुछ परिस्थितियाँ हैं, जहाँ आपको इसे ध्यान में रखना होगा। उदाहरण के लिए ध्यान रखें कि बिल्डरों की सूची शेल कार्यान्वयन के साथ बदलती है (उदाहरण के लिए, mount
कभी-कभी बिजीबॉक्स के लिए बिलिन है sh
), और उदाहरण के bash
लिए पर्यावरण से फ़ंक्शन प्राप्त कर सकते हैं।
- यदि
$PATH
सापेक्ष पथ घटक होते हैं (आमतौर पर .
या खाली स्ट्रिंग जो दोनों वर्तमान निर्देशिका को संदर्भित करते हैं, लेकिन कुछ भी हो सकता है), शेल के आधार पर, command -v cmd
एक निरपेक्ष पथ का उत्पादन नहीं कर सकता है। इसलिए आपके द्वारा चलाए command -v
जा रहे समय पर प्राप्त होने वाला मार्ग आपके बाद cd
कहीं और मान्य नहीं होगा ।
- उपाख्यानात्मक: ksh93 खोल के साथ, अगर
/opt/ast/bin
(हालांकि कि सटीक पथ विभिन्न प्रणालियों मेरा मानना है कि पर भिन्न हो सकते हैं) आप में है $PATH
, ksh93 उपलब्ध कुछ अतिरिक्त builtins (कर देगा chmod
, cmp
, cat
...), लेकिन command -v chmod
वापस आ जाएगी /opt/ast/bin/chmod
, भले ही उस मार्ग नहीं करता ' टी मौजूद है।
यह निर्धारित करना कि क्या कोई आदेश मौजूद है
यह जानने के लिए कि क्या कोई दी गई आज्ञा मानक रूप से मौजूद है, आप यह कर सकते हैं:
if command -v given-command > /dev/null 2>&1; then
echo given-command is available
else
echo given-command is not available
fi
जहां एक का उपयोग करना चाहते हो सकता है which
(t)csh
में csh
और tcsh
, आप ज्यादा विकल्प नहीं है। में tcsh
, यह ठीक है जैसा which
कि बिल्टइन है। इसमें csh
, वह सिस्टम which
कमांड होगा, जो कुछ मामलों में आप जो चाहते हैं वह नहीं कर सकते हैं।
केवल कुछ गोले में आदेश खोजें
ऐसा मामला जहां इसका उपयोग करने का कोई मतलब हो सकता which
है, यदि आप एक कमांड का रास्ता जानना चाहते हैं, तो संभावित शेल बिल्डरों या कार्यों को अनदेखा करना bash
, csh
(नहीं tcsh
) dash
, या Bourne
शेल स्क्रिप्ट, जो कि शेल whence -p
(जैसे ksh
या zsh
) नहीं है , command -ev
(जैसे yash
), whatis -p
( rc
, akanga
) या एक बिलिन which
(जैसे tcsh
या zsh
) सिस्टम पर जहां which
उपलब्ध है और csh
स्क्रिप्ट नहीं है ।
यदि उन शर्तों को पूरा किया जाता है, तो:
echo=$(which echo)
आप पहली बार के पथ देना होगा echo
में $PATH
(कोने मामलों को छोड़कर), चाहे echo
कोई शेल भी निर्मित / उर्फ / फंक्शन है या नहीं होता है।
अन्य गोले में, आप पसंद करेंगे:
- zsh :
echo==echo
या echo=$commands[echo]
याecho=${${:-echo}:c}
- ksh , zsh :
echo=$(whence -p echo)
- यश :
echo=$(command -ev echo)
- आर सी , akanga :
echo=`whatis -p echo`
(रिक्तियों के साथ रास्तों में से सावधान रहना)
- मछली :
set echo (type -fp echo)
ध्यान दें कि यदि आप जो करना चाहते हैं , उस कमांड को चलाना है echo
, तो आपको इसका रास्ता निकालना नहीं है, आप बस कर सकते हैं:
env echo this is not echoed by the builtin echo
उदाहरण के लिए, tcsh
बिलिन का which
उपयोग करने से रोकने के लिए :
set Echo = "`env which echo`"
जब आपको बाहरी आदेश की आवश्यकता होती है
एक और मामला जहां आप उपयोग करना चाह सकते हैं which
, जब आपको वास्तव में बाहरी कमांड की आवश्यकता होती है । POSIX के लिए आवश्यक है कि सभी शेल बिल्डिंग्स (जैसे command
) बाहरी कमांड के रूप में भी उपलब्ध हों, लेकिन दुर्भाग्य से यह command
कई प्रणालियों के लिए ऐसा नहीं है । उदाहरण के लिए, command
लिनक्स आधारित ऑपरेटिंग सिस्टम पर कमांड खोजना दुर्लभ है, जबकि उनमें से अधिकांश में एक which
कमांड है (हालांकि विभिन्न विकल्पों और व्यवहारों के साथ अलग-अलग हैं)।
मामले जहाँ आप एक बाहरी कमांड चाहते हो सकता है जहाँ भी आप एक POSIX शेल को लागू किए बिना एक कमांड निष्पादित करेंगे।
system("some command line")
, popen()
... सी या विभिन्न भाषाओं के कार्यों कि कमांड लाइन पार्स करने के लिए एक खोल आह्वान, इसलिए करते हैं system("command -v my-cmd")
उन में काम करते हैं। इसका एक अपवाद यह होगा कि perl
यदि कोई शेल विशेष वर्ण (अंतरिक्ष के अलावा) को नहीं देखता है तो शेल को कैसे अनुकूलित किया जाएगा । यह भी इसके backtick ऑपरेटर पर लागू होता है:
$ perl -le 'print system "command -v emacs"'
-1
$ perl -le 'print system ":;command -v emacs"'
/usr/bin/emacs
0
$ perl -e 'print `command -v emacs`'
$ perl -e 'print `:;command -v emacs`'
/usr/bin/emacs
इसके बाद के :;
संस्करण perl
वहाँ एक खोल आह्वान करने के लिए मजबूर करता है। उपयोग करके which
, आपको उस ट्रिक का उपयोग नहीं करना होगा।
which
एक इंटरैक्टिव शेल संदर्भ मान रहे हैं। यह प्रश्न टैग / पोर्टेबिलिटी है। इसलिए मैं इस संदर्भ में प्रश्न की व्याख्या करता हूं कि "which
किसी दिए गए नाम के पहले निष्पादन योग्य को खोजने के बजाय क्या उपयोग करना है$PATH
"। अधिकांश जवाब और कारणwhich
उपनामों, बिल्डरों और कार्यों से निपटने के लिए हैं, जो कि अधिकांश वास्तविक दुनिया में पोर्टेबल शेल स्क्रिप्ट सिर्फ अकादमिक रुचि के हैं। शेल स्क्रिप्ट चलाने के दौरान स्थानीय रूप से परिभाषित उपनामों को विरासत में नहीं मिलता है (जब तक कि आप इसे स्रोत नहीं करते.
)।