क्यों नहीं "जो" का उपयोग करें? फिर क्या उपयोग करें?


328

जब एक निष्पादन के लिए पथ की तलाश में या जाँच अगर आप एक यूनिक्स शेल में एक कमांड नाम दर्ज क्या होगा, विभिन्न उपयोगिताओं की अधिकता (है which, type, command, whence, where, whereis, whatis, hash, आदि)।

हम अक्सर सुनते हैं कि whichइससे बचना चाहिए। क्यों? हमें इसके बजाय क्या उपयोग करना चाहिए?


3
मुझे लगता है कि उपयोग करने के खिलाफ अधिकांश तर्क whichएक इंटरैक्टिव शेल संदर्भ मान रहे हैं। यह प्रश्न टैग / पोर्टेबिलिटी है। इसलिए मैं इस संदर्भ में प्रश्न की व्याख्या करता हूं कि " whichकिसी दिए गए नाम के पहले निष्पादन योग्य को खोजने के बजाय क्या उपयोग करना है $PATH"। अधिकांश जवाब और कारण whichउपनामों, बिल्डरों और कार्यों से निपटने के लिए हैं, जो कि अधिकांश वास्तविक दुनिया में पोर्टेबल शेल स्क्रिप्ट सिर्फ अकादमिक रुचि के हैं। शेल स्क्रिप्ट चलाने के दौरान स्थानीय रूप से परिभाषित उपनामों को विरासत में नहीं मिलता है (जब तक कि आप इसे स्रोत नहीं करते .)।
मैटबियनको

5
@MattBianco, हाँ, csh(और whichअभी भी cshअधिकांश वाणिज्यिक यूनियनों पर एक स्क्रिप्ट है) ~/.cshrcगैर-संवादात्मक होने पर पढ़ता है । यही कारण है कि आप देखेंगे csh स्क्रिप्ट आमतौर पर साथ शुरू होती हैं #! /bin/csh -fwhichइसका कारण यह नहीं है कि इसका उद्देश्य आपको उपनाम देना है, क्योंकि यह (इंटरैक्टिव) उपयोगकर्ताओं के लिए एक उपकरण के रूप में है csh। POSIX गोले उपयोगकर्ताओं के पास है command -v
स्टीफन चेज़लस

@rudimeier, तो उत्तर हमेशा(t)cshtypecommand -v होगा जब तक कि आपका शेल नहीं है (या आपको कोई आपत्ति नहीं है यदि यह आपको सही परिणाम नहीं देता है), उपयोग करें या इसके बजायक्यों के लिए जवाब देखें ।
स्टीफन चेज़लस

1
@rudimeier, ( stat $(which ls)कई कारणों के लिए गलत है (लापता --, लापता उद्धरण), न केवल उपयोग which)। आप उपयोग करेंगे stat -- "$(command -v ls)"। यह lsमाना जाता है कि वास्तव में फाइल सिस्टम पर पाया जाने वाला एक कमांड है (आपके शेल का बिलियन नहीं, या उपनाम का कार्य)। whichआपको गलत रास्ता दे सकता है (आपके द्वारा दर्ज किए जाने पर आपका शेल निष्पादित नहीं होने वाला पथ ls) या आपको किसी अन्य शेल के कॉन्फ़िगरेशन में परिभाषित रूप में एक उपनाम देता है ...
स्टीफन चेज़लस

1
@rudimeier, फिर से, कई स्थितियां हैं जिनके तहत कई whichकार्यान्वयन आपको नहीं देंगे जो lsकि आपके लुक-अप $PATH(चाहे lsआपके शेल में क्या हो सकता है) के लुक-अप द्वारा पाया जाएगा । sh -c 'command -v ls', या zsh -c 'rpm -q --whatprovides =ls'आपको सही उत्तर देने की अधिक संभावना है। यहाँ बात यह है कि whichयह एक टूटी हुई विरासत है csh
स्टीफन चेज़लस

जवाबों:


365

यहाँ आप कभी नहीं सोचा था कि आप इसके बारे में जानना कभी नहीं चाहेंगे:

सारांश

बॉर्न जैसी शेल स्क्रिप्ट में एक निष्पादन योग्य का पथनाम प्राप्त करने के लिए (कुछ कैविएट हैं; नीचे देखें):

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 के दशक के उत्तरार्ध तक शुरुआती यूनिक्स गोले का कोई कार्य या उपनाम नहीं था। केवल निष्पादन में पारंपरिक देख रहे हैं $PATHcsh1978 के आसपास उपनामों को पेश किया (हालांकि मई 1979 में cshपहली बार जारी किया गया था 2BSD), और .cshrcशेल (हर शेल को अनुकूलित करने के लिए उपयोगकर्ताओं के लिए प्रसंस्करण भी , जैसा कि स्क्रिप्ट में इंटरएक्टिव नहीं होने पर भी cshपढ़ता है .cshrc)।

जबकि बॉर्न शेल पहली बार 1979 में यूनिक्स वी 7 में जारी किया गया था, फ़ंक्शन समर्थन केवल बहुत बाद में (एसवीआर 2 में 1984) जोड़ा गया था, और वैसे भी, इसमें कभी भी कुछ rcफ़ाइल नहीं थी ( .profileआपके पर्यावरण को कॉन्फ़िगर करने के लिए, शेल प्रति नहीं )।

csh बॉर्न शेल की तुलना में बहुत अधिक लोकप्रिय हो गया (हालांकि इसमें बॉर्न शेल की तुलना में एक बहुत बुरा सिंटैक्स था) यह इंटरैक्टिव उपयोग के लिए बहुत अधिक सुविधाजनक और अच्छी सुविधाओं को जोड़ रहा था।

में 3BSD(1980), एक whichcsh स्क्रिप्ट के लिए जोड़ा गया है cshउन एक निष्पादन की पहचान में मदद करने के लिए, और यह एक मुश्किल से भिन्न स्क्रिप्ट आप के रूप में मिल सकता है whichकई वाणिज्यिक Unices आजकल (Salaris, HP / UX, AIX या Tru64 की तरह) पर।

वह स्क्रिप्ट उपयोगकर्ता को पढ़ता है ~/.cshrc(जैसे कि सभी cshस्क्रिप्ट तब तक लागू नहीं होती हैं csh -f), और एलियासेस की सूची में दिए गए कमांड नाम (ओं) और $path(जो सरणी के cshआधार पर बनाए रखता है $PATH) को देखता है ।

यहाँ आप जाते हैं, whichउस समय सबसे लोकप्रिय शेल के लिए पहली बार आया cshथा (और 90 के दशक के मध्य तक अभी भी लोकप्रिय था), जो मुख्य कारण है कि यह पुस्तकों में प्रलेखित हुआ और अभी भी व्यापक रूप से उपयोग किया जाता है।

ध्यान दें, यहां तक ​​कि एक cshउपयोगकर्ता के लिए, वह whichcsh स्क्रिप्ट जरूरी नहीं कि आपको सही जानकारी दे। इसे एलियन्स में परिभाषित किया गया है ~/.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 द्वारा प्रायोजित ) का सार्वजनिक डोमेन कार्यान्वयन , zsh1989 और 1991 के बीच में आया।

हालांकि, ऐश का मतलब बॉर्न शेल के लिए एक प्रतिस्थापन था, हालांकि typeबाद में (नेटबीएसडी 1.3 और फ्रीबीएसडी 2.3 में) एक बिलिन नहीं था , हालांकि यह था hash -v। OSF / 1 /bin/shमें एक typeबिल्डिन था जो हमेशा OSF / 1 v3.x तक 0 लौटाता था। पथ प्रिंट करने के लिए एक विकल्प bashनहीं whenceजोड़ा गया ( जैसा होगा ) और सभी मिलान आदेशों को रिपोर्ट करने के लिए। बनाया निर्मित और एक जोड़ा आदेश की तरह कार्य कर रहा है । उन सभी को है।-ptypetype -pwhence -p-atcshwhichwherebashtype -azsh

fishखोल (2005) एक है typeआदेश एक समारोह के रूप में लागू।

इस whichबीच csh स्क्रिप्ट को NetBSD से हटा दिया गया था (क्योंकि यह tcsh में बनाया गया था और अन्य गोले में ज्यादा इस्तेमाल नहीं किया गया था), और इसमें जो फंक्शनलिटी जोड़ी गई है whereis(जब इनवॉइस किया जाता है which, तो whereisऐसा व्यवहार करता है कि whichसिवाय इसके कि यह केवल एग्जीक्यूटिव दिखता है $PATH)। OpenBSD और FreeBSD में, whichC में लिखे एक को भी बदल दिया गया जो $PATHकेवल कमांड में दिखता है ।

क्रियान्वयन

whichविभिन्न सिंटैक्स और व्यवहार के साथ विभिन्न यूनियनों पर एक कमांड के दर्जनों कार्यान्वयन हैं।

लिनक्स पर (बिल्टइन के बगल में tcshऔर zsh) हम कई कार्यान्वयन पाते हैं। उदाहरण के लिए हाल ही में डेबियन सिस्टम पर, यह एक साधारण पोसिक्स शेल स्क्रिप्ट है जो कमांड में दिखता है $PATH

busyboxएक whichकमांड भी है ।

वहाँ एक है GNU whichजो शायद सबसे असाधारण है। यह विस्तारित करने का प्रयास करता है कि whichcsh स्क्रिप्ट ने अन्य गोले के लिए क्या किया है: आप इसे बता सकते हैं कि आपके उपनाम और कार्य क्या हैं ताकि यह आपको एक बेहतर उत्तर दे सके (और मेरा मानना ​​है कि कुछ लिनक्स वितरणों ने इसके लिए कुछ वैश्विक उपनाम सेट किए हैं 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 -aksh93 में और अन्य गोले में, आप उपयोग कर सकते हैं 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, आपको उस ट्रिक का उपयोग नहीं करना होगा।


24
@ जो, कई वाणिज्यिक यूनियनों पर whichएक cshस्क्रिप्ट है। कारण ऐतिहासिक है, इसीलिए मैंने इतिहास दिया, इसलिए लोग समझते हैं कि यह कहां से आया है, लोगों को इसका उपयोग करने की आदत क्यों है और वास्तव में ऐसा कोई कारण नहीं है कि आपको इसका उपयोग करना चाहिए। और हाँ, कुछ लोग (t) csh का उपयोग करते हैं। हर कोई अभी तक लिनक्स का उपयोग नहीं करता है
स्टीफन चेज़लस

12
इस पोस्ट को पढ़ने के बाद, मुझे उत्तर के लिए बहुत सारे संदर्भ मिल गए हैं, लेकिन उत्तर स्वयं नहीं। जहां इस पोस्ट में वास्तव में यह कहा गया है कि क्यों नहीं उपयोग करना है which, उन चीजों के विपरीत जो आप उपयोग whichकरने की कोशिश कर रहे हैं, का इतिहास which, कार्यान्वयन which, अन्य कमांड संबंधित कार्य करने के लिए, या वास्तव में उपयोग करने के लिए कारण which? अन्य कमांड बेहतर क्यों हैं ? वे अलग तरीके से क्या करते हैं which? वे इसके नुकसान से कैसे बचते हैं? यह उत्तर वास्तव में समस्याओं की तुलना में विकल्पों के साथ समस्याओं पर अधिक शब्द खर्च करता है which
user62251

1
उत्तर का दावा करने के विपरीत, command -vनिष्पादन की अनुमति के लिए जाँच नहीं करता है, कम से कम यदि आप इसे बिना पथ के शुद्ध फ़ाइल नाम तर्क से कहते हैं। मैंने डैश 0.5.8 और GNU बैश 4.3.48 का परीक्षण किया।
जर्नो

2
@ स्टीफनचेलजैस अगर मैं touch /usr/bin/mytestfileइसके द्वारा नई फाइल बनाता हूं और उसके बाद चला जाता हूं command -v mytestfile, तो यह रास्ता देगा (जबकि which mytestfileऐसा नहीं है)।
जर्नो

2
@ कर्णो, ओह हाँ, आप सही कह रहे हैं। bashयदि यह एक निष्पादन योग्य नहीं मिल सकता है, तो एक गैर-निष्पादन योग्य फ़ाइल पर बस जाएगा, इसलिए यह "ओके" है (हालांकि व्यवहार में कोई एक त्रुटि होगी command -v/ typeवापस आ जाएगी ) क्योंकि यह कमांड है जिसे आप चलाने पर निष्पादित करने का प्रयास करेंगे mytestfile, लेकिन dashव्यवहार छोटा है, जैसे कि एक निष्पादन योग्य के cmdआगे एक गैर-निष्पादन योग्य है, command -vनिष्पादन योग्य एक को निष्पादित करते समय गैर-निष्पादन योग्य रिटर्न देता है cmd(गलत एक हैशेड भी है)। FreeBSD sh(भी आधारित ash) में एक ही बग है। zsh, यश, ksh, mksh, bash as sh ठीक हैं।
स्टीफन चेजलस

47

जिन कारणों से कोई उपयोग नहीं करना चाहता है, whichउन्हें पहले ही समझाया जा चुका है, लेकिन यहां कुछ प्रणालियों पर कुछ उदाहरण दिए गए हैं, जहां whichवास्तव में विफल होते हैं।

बॉर्न-जैसे गोले पर, हम आउटपुट के whichसाथ तुलना कर रहे हैं type( typeशेल बिलियन होने के नाते, इसका मतलब जमीनी सच्चाई है, क्योंकि यह शेल हमें बता रहा है कि यह एक कमांड कैसे लागू करेगा)।

कई मामले कोने के मामले होते हैं , लेकिन ध्यान में रखते हैं कि which/ typeअक्सर कोने के मामलों में उपयोग किया जाता है (जैसे अप्रत्याशित व्यवहार का उत्तर खोजने के लिए: पृथ्वी पर क्यों वह आदेश ऐसा व्यवहार कर रहा है, जिसे मैं कह रहा हूं? )।

अधिकांश सिस्टम, अधिकांश बॉर्न-जैसे गोले: फ़ंक्शन

सबसे स्पष्ट मामला कार्यों के लिए है:

$ type ls
ls is a function
ls ()
{
[ -t 1 ] && set -- -F "$@";
command ls "$@"
}
$ which ls
/bin/ls

कारण यह है कि whichकेवल निष्पादक के बारे में रिपोर्ट करता है, और कभी-कभी उपनामों के बारे में (हालांकि हमेशा आपके शेल के नहीं), फ़ंक्शन नहीं।

GNU का कौन सा मैन पेज टूटा हुआ है (जैसा कि वे उद्धृत करना भूल गए $@) उदाहरण के लिए इसका उपयोग कार्यों को रिपोर्ट करने के लिए कैसे करें, लेकिन सिर्फ उपनाम के लिए पसंद है, क्योंकि यह एक शेल सिंटैक्स पार्सर को लागू नहीं करता है, यह आसानी से मूर्ख है:

$ which() { (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot "$@";}
$ f() { echo $'\n}\ng ()\n{ echo bar;\n}\n' >> ~/foo; }
$ type f
f is a function
f ()
{
echo '
}
g ()
{ echo bar;
}
' >> ~/foo
}
$ type g
bash: type: g: not found
$ which f
f ()
{
echo '
}
$ which g
g ()
{ echo bar;
}

अधिकांश सिस्टम, अधिकांश बॉर्न-जैसे गोले: बिलिंस

एक अन्य स्पष्ट मामला बिलिंस या कीवर्ड्स हैं, क्योंकि whichबाहरी कमांड होने के कारण यह जानने का कोई तरीका नहीं है कि आपके शेल में कौन से बिल्डिंग्स हैं (और कुछ शेल जैसे zsh, bashया kshबिलिन को गतिशील रूप से लोड कर सकते हैं):

$ type echo . time
echo is a shell builtin
. is a shell builtin
time is a shell keyword
$ which echo . time
/bin/echo
which: no . in (/bin:/usr/bin)
/usr/bin/time

(कि zshजहां बनाया गया whichहै पर लागू नहीं होता है)

Solaris 10, AIX 7.1, HP / UX 11i, Tru64 5.1 और कई अन्य:

$ csh
% which ls
ls:   aliased to ls -F
% unalias ls
% which ls
ls:   aliased to ls -F
% ksh
$ which ls
ls:   aliased to ls -F
$ type ls
ls is a tracked alias for /usr/bin/ls

ऐसा इसलिए है क्योंकि अधिकांश वाणिज्यिक यूनियनों पर, which(3BSD पर मूल कार्यान्वयन की तरह) एक cshस्क्रिप्ट है जो पढ़ती है ~/.cshrc। जिन उपनामों की यह रिपोर्ट करेगा, वे वहां परिभाषित किए गए हैं, चाहे आपके द्वारा वर्तमान में परिभाषित किए गए उपनामों की परवाह किए बिना और वास्तव में आपके द्वारा उपयोग किए जा रहे शेल की परवाह किए बिना।

HP / UX या Tru64 में:

% echo 'setenv PATH /bin:/usr/bin' >> ~/.cshrc
% setenv PATH ~/bin:/bin:/usr/bin
% ln -s /bin/ls ~/bin/
% which ls
/bin/ls

(Solaris और AIX संस्करणों ने उस मुद्दे को $pathपढ़ने से पहले सहेजने ~/.cshrcऔर आदेश को देखने से पहले इसे पुनर्स्थापित करने का निर्णय लिया है)

$ type 'a b'
a b is /home/stephane/bin/a b
$ which 'a b'
no a in /usr/sbin /usr/bin
no b in /usr/sbin /usr/bin

या:

$ d="$HOME/my bin"
$ mkdir "$d"; PATH=$PATH:$d
$ ln -s /bin/ls "$d/myls"
$ type myls
myls is /home/stephane/my bin/myls
$ which myls
no myls in /usr/sbin /usr/bin /home/stephane/my bin

(बेशक, एक cshस्क्रिप्ट होने के नाते आप यह उम्मीद नहीं कर सकते कि इसमें रिक्त स्थान वाले तर्कों के साथ काम किया जाएगा ...)

सेंटोस 6.4, बैश

$ type which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
$ alias foo=': "|test|"'
$ which foo
alias foo=': "|test|"'
        /usr/bin/test
$ alias $'foo=\nalias bar='
$ unalias bar
-bash: unalias: bar: not found
$ which bar
alias bar='

उस सिस्टम पर, एक उपनाम परिभाषित सिस्टम चौड़ा है जो GNU whichकमांड को लपेटता है ।

क्योंकि फर्जी उत्पादन होता है whichके उत्पादन में पढ़ता bashहै alias, लेकिन इसे सही रूप पार्स करने के लिए पता नहीं है और heuristics का उपयोग करता है (प्रति पंक्ति एक उर्फ, पहले एक के बाद आदेश मिल गया के लिए लग रहा है |, ;, &...)

CentOS पर सबसे बुरी बात यह है कि zshइसमें बिलकुल ठीक से whichनिर्मित कमांड है, लेकिन CentOS ने इसे गैर-कार्यशील उपनाम के साथ GNU में बदलकर तोड़ने में कामयाब रहा which

डेबियन 7.0, ksh93:

(हालांकि कई गोले वाली अधिकांश प्रणालियों पर लागू होता है)

$ unset PATH
$ which which
/usr/local/bin/which
$ type which
which is a tracked alias for /bin/which

डेबियन पर, /bin/whichएक /bin/shस्क्रिप्ट है। मेरे मामले में, यह shहोने dashपर भी ऐसा ही है bash

एक सेट नहीं PATHनिष्क्रिय करने के लिए नहीं है PATHदेखने के लिए, लेकिन प्रणाली का उपयोग का मतलब है डिफ़ॉल्ट पथ जो डेबियन पर दुर्भाग्य से, कोई भी नहीं पर सहमत हैं ( dashऔर bashहै /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin, zshहै /bin:/usr/bin:/usr/ucb:/usr/local/bin, ksh93है /bin:/usr/bin, mkshहै /usr/bin:/bin( $(getconf PATH)), execvp()में की तरह ( env) है :/bin:/usr/bin(हाँ, वर्तमान निर्देशिका में पहली बार लग रहा है! ))।

क्यों कौन सा है whichयह ऊपर गलत है क्योंकि यह उपयोग कर रहा है हो जाता है dash's डिफ़ॉल्ट PATHरूप से अलग है ksh93की

यह GNU के साथ बेहतर नहीं है whichजो रिपोर्ट करता है:

which: no which in ((null))

(दिलचस्प बात यह है /usr/local/bin/whichकि मेरे सिस्टम पर वास्तव में एक ऐसी akangaस्क्रिप्ट है जो वास्तव में एक स्क्रिप्ट है जो akangaएक rcशेल व्युत्पन्न है जहां डिफ़ॉल्ट PATHहै /usr/ucb:/usr/bin:/bin:.))

बैश, किसी भी प्रणाली:

एक क्रिस अपने जवाब में बात कर रहा है :

$ PATH=$HOME/bin:/bin
$ ls /dev/null
/dev/null
$ cp /bin/ls bin
$ type ls
ls is hashed (/bin/ls)
$ command -v ls
/bin/ls
$ which ls
/home/chazelas/bin/ls

hashमैन्युअल रूप से कॉल करने के बाद भी :

$ type -a which
which is /usr/local/bin/which
which is /usr/bin/which
which is /bin/which
$ hash -p /bin/which which
$ which which
/usr/local/bin/which
$ type which
which is hashed (/bin/which)

अब एक मामला जहां whichऔर कभी-कभी typeविफल होता है:

$ mkdir a b
$ echo '#!/bin/echo' > a/foo
$ echo '#!/' > b/foo
$ chmod +x a/foo b/foo
$ PATH=b:a:$PATH
$ which foo
b/foo
$ type foo
foo is b/foo

अब, कुछ गोले के साथ:

$ foo
bash: ./b/foo: /: bad interpreter: Permission denied

दूसरों के साथ:

$ foo
a/foo

न तो पहले से पता कर सकते हैं whichऔर न ही निष्पादित किया जा सकता है। कुछ गोले की तरह , या , जब लागू वास्तव में चलाने का प्रयास करेंगे , जबकि अन्य लोगों (जैसे, और किसी त्रुटि की रिपोर्ट , , , , ) चलेंगे की विफलता पर पर सिस्टम कॉल ।typeb/foobashkshyashfoob/foozshashcshBournetcsha/fooexecve()b/foo


mkshवास्तव में डिफ़ॉल्ट के लिए कुछ अलग का उपयोग करता है $PATH: सबसे पहले, ऑपरेटिंग सिस्टम के संकलन-समय स्थिरांक _PATH_DEFPATHका उपयोग किया जाता है (आमतौर पर बीएसडी पर), फिर, confstr(_CS_PATH, …)उपयोग किया जाता है (POSIX), और यदि दोनों मौजूद नहीं हैं या विफल हैं, तो /bin:/usr/bin:/sbin:/usr/sbinइसका उपयोग किया जाता है।
mirabilos

1
आपके 1 उदाहरण में, भले ही lsयह एक फ़ंक्शन है lsजो PATH से उपयोग कर रहा है। और whichआपको बताने के लिए ठीक है कि कौन सा उपयोग किया जाता है /usr/bin/ls या /usr/local/bin/ls। मैं नहीं देखता कि "क्यों इस्तेमाल नहीं किया गया" ....
rudimeier

@rudimeier, कि which lsमुझे इस बात की /bin/lsपरवाह किए बिना कि lsफ़ंक्शन कॉल करता है /bin/lsया /opt/gnu/bin/lsया dirबिल्कुल भी नहीं। IOW, which(जो कार्यान्वयन, IMMV) कुछ अप्रासंगिक दे रहा है
स्टीफन चेज़लस

1
@ StéphaneChazelas। नहीं नहीं नहीं। मुझे पहले से ही पता है कि मेरा lsएक फंक्शन है। मुझे पता है कि मेरे lsकार्य से फोन lsकिया जा रहा है PATH। अब whichबताता हूं कि फाइल कहां है। आप केवल एक ही उपयोग का मामला देखते हैं: "मेरा शेल इस कमांड के साथ क्या करेगा।" इस उपयोग के लिए मामला whichगलत है, सही है। लेकिन अन्य उपयोग के मामले हैं जहां (GNU) whichबिल्कुल सही बात है।
रूडाइमियर

@rudimeter, whichकार्यान्वयन पर निर्भर करता है । कुछ आपको बताएंगे कि यह एक उपनाम है (यदि आपके पास एक उपनाम कॉन्फ़िगर किया गया है, या यदि ~/.cshrcआपके घर में ऐसा कोई उपनाम है), तो कुछ आपको कुछ शर्तों के तहत एक रास्ता देगा लेकिन गलत। sh -c 'command -v ls', हालांकि सही नहीं है फिर भी आपको उस अलग आवश्यकता (और मानक भी है) का सही उत्तर देने की अधिक संभावना है।
स्टीफन चेज़लस

21

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


6

UNIX स्पिरिट में: प्रत्येक प्रोग्राम को एक काम अच्छे से करें।

यदि लक्ष्य का उत्तर देना है: कौन सा निष्पादन योग्य इस नाम के साथ मौजूद है ?

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

यदि इस लिपि का उपयोग किया जाता है, तो इसका उत्तर साफ, सरल और उपयोगी है।

यह लक्ष्य आपके प्रश्न के पहले वाक्य से मेल खाएगा:

जब एक निष्पादन योग्य…

यदि आपके पास एक ऐसी प्रणाली है जिसमें एक निष्पादन योग्य नहीं है जिसे (अधिकांश लिनक्स सिस्टम में एक है) तो आप पाथ में एक से ~/bin/whichपहले एक बना सकते हैं /bin/ताकि व्यक्तिगत निष्पादन योग्य ओवरराइड सिस्टम वाले जैसे कि इस पोस्ट के निचले भाग में हों:

वह निष्पादन योग्य सूची (डिफ़ॉल्ट रूप से) PATH में पाए जाने वाले सभी निष्पादकों को सूचीबद्ध करेगी । यदि केवल पहले की आवश्यकता है, तो विकल्प -fउपलब्ध है।


इस बिंदु पर हम एक अलग लक्ष्य में आते हैं:

शेल क्या करेगा (पार्स करने के बाद)

यह आपके दूसरे वाक्य से आता है:

यदि आप एक यूनिक्स खोल में एक कमांड नाम दर्ज करते हैं तो क्या होगा

यह दूसरा विषय एक प्रश्न का एक अच्छा उत्तर खोजने का प्रयास करता है, जिसका उत्तर देना कठिन है। शेल में अलग-अलग व्याख्याएं, कोने के मामले और (कम से कम) अलग-अलग व्याख्याएं हैं। इसे जोड़ना:

वहाँ विभिन्न उपयोगिताओं (जो, प्रकार, आदेश, कहाँ, कहाँ, कहाँ, क्या, हैश, आदि) की अधिकता है।

और निश्चित रूप से, सभी प्रयास उस लक्ष्य से मेल खाते हैं।


किससे बचें?

हम अक्सर सुनते हैं कि किससे बचना चाहिए।

मुझे आश्चर्य है: अगर whichठीक काम करता है ( तो कम से कम डेबियन में) क्यों कहा जाना चाहिए ?

UNIX स्पिरिट में: प्रत्येक प्रोग्राम को एक काम अच्छे से करें।

बाहरी कार्यक्रम whichएक बात कर रहा है: पथ के रूप में एक ही नाम है उस पर पहले निष्पादन का पता लगाएं आदेश नाम । और यथोचित रूप से अच्छा कर रहा है।

मुझे किसी अन्य कार्यक्रम या उपयोगिता का पता नहीं है जो इस प्रश्न का उत्तर अधिक मौलिक तरीके से देता है। जैसे, यह उपयोगी है और जरूरत पड़ने पर इस्तेमाल किया जा सकता है।

निकटतम विकल्प प्रतीत होता है: command -pv commandNameलेकिन यह भी निर्मित और उपनामों के बारे में रिपोर्ट करेगा। एक ही जवाब नहीं।

बेशक, whichयह सीमित है, यह सभी सवालों का जवाब नहीं देता है , कोई भी उपकरण ऐसा नहीं कर सकता है (ठीक है, अभी तक नहीं ...)। लेकिन यह तब उपयोगी होता है जब इसका उपयोग उस प्रश्न का उत्तर देने के लिए किया जाता है जिसे उत्तर देने के लिए डिज़ाइन किया गया था (ऊपर एक)। बहुत कुछ edसीमित था और फिर sedदिखाई दिया (या vi/ vim)। या जैसे awkसीमित था और पर्ल दिखाई और विस्तार किया। फिर भी, ed, sedया / और awkजहां विशिष्ट उपयोग मामलों है vimया perlकर रहे हैं नहीं सबसे अच्छा उपकरण।

क्यों?

शायद इसलिए कि whichएक शेल उपयोगकर्ता द्वारा पूछे जाने वाले प्रश्न का केवल एक हिस्सा उत्तर देता है:

जब मैं एक कमांडनाम टाइप करता हूं, तो क्या निष्पादित किया जा रहा है?


बाहरी जो

जो बाहरी निष्पादन योग्य के रूप में (कई प्रणालियों में) उपलब्ध होना चाहिए।
उस बाहरी उपकरण को कॉल करने का एकमात्र निश्चित तरीका है कि शेल से बाहर जाने के लिए env का उपयोग करें और फिर कॉल करें which(जो सभी शेल में काम करता है):

 $ env which which
 /usr/bin/which

या पूर्ण पथ का उपयोग करें which(जो विभिन्न प्रणालियों पर भिन्न हो सकते हैं):

 /usr/bin/which which 

इसकी hackजरूरत क्यों है ? क्योंकि कुछ गोले (विशेष रूप से zsh) छिपते हैं which:

 $ zsh -c 'which which'
 which: shell built-in command

एक बाहरी उपकरण (जैसे env) होने के नाते पूरी तरह से बताता है कि यह शेल आंतरिक जानकारी की रिपोर्ट क्यों नहीं करेगा। जैसे उपनाम, फ़ंक्शंस, बिल्डिंस, स्पेशल बिलिंस, शेल (नॉन-एक्सपोर्टेड) ​​वैरिएबल, आदि:

 $ env which ls
 /usr/bin/ls
 $ env which ll       # empty output

ll(या एक सामान्य उपनाम के लिए ll='ls -l') का खाली आउटपुट इंगित करता है कि llएक निष्पादन योग्य कार्यक्रम से संबंधित नहीं है, या कम से कम, कि llPATH में कोई निष्पादन योग्य फ़ाइल नाम नहीं है । के उपयोग के llइस मामले में, कुछ और ही कहना चाहिए, एक उपनाम:

 $ type ll
 ll is aliased to `ls -l'

type तथा command

आदेश typeऔर command -vPOSIX द्वारा अनुरोध किया जाता है। उन्हें सबसे अधिक गोले में काम करने की उम्मीद की जानी चाहिए, और वे करते हैं, सिवाय csh, tsh, fish और rc में।

दोनों कमांड का उपयोग एक अन्य दृष्टिकोण प्रदान करने के लिए किया जा सकता है कि किस कमांड को निष्पादित किया जाएगा।

whence, where, whereis, whatis,hash

फिर, देखते हैं whence, where, whereis, whatis, hash, और कुछ अन्य। सभी अलग-अलग सवालों के जवाब। सभी अलग-अलग गोले में अलग-अलग तरीके से काम करते हैं। शायद, के whenceबाद सबसे आम है type। अन्य विशेष समाधान हैं जो अलग-अलग तरीकों से एक ही प्रश्न का उत्तर देते हैं।

हमें इसके बजाय क्या उपयोग करना चाहिए?

शायद whichपहली बार पता करने के लिए अगर वहाँ के नाम से एक निष्पादन मौजूद commandname , तो typeऔर commandऔर फिर, अगर commandname अभी तक पाया नहीं किया गया है: whence, where, whereis, whatis, hashइसी क्रम में।


एक whichनिष्पादन योग्य प्रदान करने के लिए शेल स्क्रिप्ट ।

#! /bin/sh
set -ef; oldIFS=$IFS; IFS=:

say()( IFS=" "; printf "%s\n" "$*"; )
say "Simplified version of which."
usage(){ say Usage: "$0" [-f] args; }
if [ "$#" -eq 0 ]; then say Missing argument(s); usage; exit 2; fi

firstmatch=0
while getopts f whichopts; do
    case "$whichopts" in
        f) firstmatch=1 ;;
        ?) usage; exit 3 ;;
    esac
done
[ "$OPTIND" -gt 1 ] && shift `expr "$OPTIND" - 1`

allret=0; [ "$#" -eq 0 ] && allret=1
for program in "$@"; do
    ret=1
    for element in $PATH''; do
        case "$program" in
            */*) element="$program"; loop=0;;
            *)   element="${element:-.}/$program"; loop=1;;
        esac
        if [ -f "$element" ] && [ -x "$element" ]; then
            say "$element"
            ret=0
            if [ "$firstmatch" -eq 1 ] || [ "$loop" -eq 0 ]; then break; fi
        fi
    done
    [ "$ret" -eq 1 ] && allret=1
done

IFS="$oldIFS"
exit "$allret"

0

हम अक्सर सुनते हैं कि किससे बचना चाहिए। क्यों? हमें इसके बजाय क्या उपयोग करना चाहिए?

मैंने ऐसा कभी नहीं सुना। कृपया विशिष्ट उदाहरण प्रदान करें। मुझे आपके लिनक्स वितरण और स्थापित सॉफ्टवेयर पैकेजों के बारे में चिंता होगी, क्योंकि यह कहां से whichआता है!

SLES 11.4 x86-64

tcsh संस्करण में 6.18.01:

> which which

which: shell built-in command.

संस्करण 3.2-147 में:

> which which

/usr/bin/which

> which -v

GNU which v2.19, Copyright (C) 1999 - 2008 Carlo Wood.
GNU which comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.

whichका हिस्सा है util-linux एक मानक पैकेज लिनक्स ऑपरेटिंग सिस्टम के भाग के रूप में उपयोग के लिए लिनक्स कर्नेल संगठन द्वारा वितरित किए। यह इन अन्य फ़ाइलों को भी प्रदान करता है

/bin/dmesg
/bin/findmnt
/bin/logger
/bin/lsblk
/bin/more
/bin/mount
/bin/umount
/sbin/adjtimex
/sbin/agetty
/sbin/blkid
/sbin/blockdev
/sbin/cfdisk
/sbin/chcpu
/sbin/ctrlaltdel
/sbin/elvtune
/sbin/fdisk
/sbin/findfs
/sbin/fsck
/sbin/fsck.cramfs
/sbin/fsck.minix
/sbin/fsfreeze
/sbin/fstrim
/sbin/hwclock
/sbin/losetup
/sbin/mkfs
/sbin/mkfs.bfs
/sbin/mkfs.cramfs
/sbin/mkfs.minix
/sbin/mkswap
/sbin/nologin
/sbin/pivot_root
/sbin/raw
/sbin/sfdisk
/sbin/swaplabel
/sbin/swapoff
/sbin/swapon
/sbin/switch_root
/sbin/wipefs
/usr/bin/cal
/usr/bin/chrp-addnote
/usr/bin/chrt
/usr/bin/col
/usr/bin/colcrt
/usr/bin/colrm
/usr/bin/column
/usr/bin/cytune
/usr/bin/ddate
/usr/bin/fallocate
/usr/bin/flock
/usr/bin/getopt
/usr/bin/hexdump
/usr/bin/i386
/usr/bin/ionice
/usr/bin/ipcmk
/usr/bin/ipcrm
/usr/bin/ipcs
/usr/bin/isosize
/usr/bin/line
/usr/bin/linux32
/usr/bin/linux64
/usr/bin/look
/usr/bin/lscpu
/usr/bin/mcookie
/usr/bin/mesg
/usr/bin/mkzimage_cmdline
/usr/bin/namei
/usr/bin/rename
/usr/bin/renice
/usr/bin/rev
/usr/bin/script
/usr/bin/scriptreplay
/usr/bin/setarch
/usr/bin/setsid
/usr/bin/setterm
/usr/bin/tailf
/usr/bin/taskset
/usr/bin/time
/usr/bin/ul
/usr/bin/uname26
/usr/bin/unshare
/usr/bin/uuidgen
/usr/bin/wall
/usr/bin/whereis
/usr/bin/which
/usr/bin/write
/usr/bin/x86_64
/usr/sbin/addpart
/usr/sbin/delpart
/usr/sbin/fdformat
/usr/sbin/flushb
/usr/sbin/freeramdisk
/usr/sbin/klogconsole
/usr/sbin/ldattach
/usr/sbin/partx
/usr/sbin/rcraw
/usr/sbin/readprofile
/usr/sbin/rtcwake
/usr/sbin/setctsid
/usr/sbin/tunelp

मेरा util-linuxसंस्करण 2.19 है। रिलीज़ नोट्स आसानी से v2.13 दिनांक (28-अगस्त -2017) को वापस मिल सकते हैं। यह निश्चित नहीं था कि बिंदु या लक्ष्य क्या था, यह निश्चित रूप से उस लंबी बात में जवाब नहीं दिया गया था जो 331 बार हुआ।


2
ध्यान दें कि सवाल यह बताता है कि यूनिक्स इसका क्या उल्लेख करता है। लिनक्स कुछ में से एक है।
Kusalananda

2
आपके which -vशो के अनुसार, वह GNU है (जो किसी अन्य उत्तर में वर्णित असाधारण है और लिनक्स के लिए किसी भी तरह से विशिष्ट नहीं है), उपयोग-लिनेक्स नहीं जो AFAIK ने कभी whichउपयोगिता शामिल नहीं की । उपयोग- linux 2.19 2011 से है, GNU जो 2.19 2008 से है।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.