`Cd` के लिए` who` कमांड काम क्यों नहीं करेगा? मैं `cd` के लिए भी निष्पादन योग्य नहीं मिल सकता है!


30

मैंने कोशिश की which cdऔर यह एक रास्ता नहीं दे रहा था लेकिन बदले में बाहर निकलें कोड 1 (साथ चेक किया गया echo $?) लौटा दिया । Coreutil cdस्वयं काम कर रहा है, इसलिए निष्पादन योग्य होना चाहिए, है ना? मैं एक के findलिए भी भागा cd, लेकिन कोई निष्पादन योग्य फ़ाइल नहीं दिखाई गई। फिर इसे कैसे लागू किया जाता है?

अद्यतन करें:

मुझे नहीं पता कि मुझे किसी अन्य पोस्ट में यह पूछना चाहिए, लेकिन जब से मुझे लगता है कि यह यहाँ अच्छा है, मैं विस्तार कर रहा हूँ (!) पोस्ट ... तो जवाब वास्तव में काफी सरल था, उसके लिए कोई निष्पादन योग्य नहीं है - क्योंकि यह है ए बिलिन - लेकिन मैंने पाया है कि कुछ बिलिन (फेडोरा में बैश शेल) निष्पादन योग्य फाइलें हैं! तो बिलियन -> कोई निष्पादन योग्य सही नहीं है मुझे लगता है? हो सकता है कि यह समझाने के लिए कि वास्तव में मामला क्या है (बिलिन कमांड्स?), जो वास्तव में यहाँ मामला है, और अधिक ध्यान केंद्रित करने के बजाय cd... पहले से पोस्ट किए गए कुछ अच्छे लिंक यह दर्शाते हैं कि बिलिन प्रोग्राम नहीं हैं ... तो वे क्या हैं? वो कैसे काम करते है? क्या वे केवल शेल के कार्य या धागे हैं?


1
इस उत्तर को पढ़ें । यह सुझाव दिया गया है कि type
बजे

7
यह क्यू एंड ए देखें कि cdएक बिलिन की आवश्यकता क्यों है : सीडी एक कार्यक्रम क्यों नहीं है? और यह एक typeऐसा क्यों है जो इससे बेहतर है which: "क्यों" का उपयोग न करें? फिर क्या उपयोग करें?
terdon

इसी तरह के सवाल यहाँ: askubuntu.com/q/613470/178596
Wilf

जवाबों:


46

कमांड cdएक निष्पादन योग्य नहीं हो सकता है

एक शेल में, cdकार्यशील निर्देशिका (CWD) को बदलने के लिए, "किसी अन्य निर्देशिका में जाने" या अधिक औपचारिक रूप से उपयोग किया जाता है। बाहरी आदेश के रूप में इसे लागू करना असंभव है:

निर्देशिका एक प्रक्रिया से संबंधित है

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

cdउदाहरण के लिए, शेल प्रक्रिया की वर्तमान कार्यशील निर्देशिका को बदलने के बारे में है bash

यदि यह एक बाहरी आदेश था, तो पथ में एक निष्पादन योग्य, जो निष्पादन योग्य चल रहा है, जो वर्तमान शेल को प्रभावित किए बिना, अपनी कार्यशील निर्देशिका के साथ एक प्रक्रिया तैयार करेगा। भले ही बाहरी कमांड यह निर्देशिका को बदल दे, बाहरी प्रक्रिया से बाहर निकलने पर वह परिवर्तन चला जाता है।

शेल बिल्डिन कमांड्स

तो यह कोई मतलब नहीं है कि के काम के लिए एक बाहरी आदेश चलाने के लिए cd। कमांड cdको वर्तमान में चल रही शेल प्रक्रिया में बदलाव लागू करने की आवश्यकता है।

ऐसा करने के लिए, यह शेल का एक "बिलियन कमांड" है।

बिलिन कमांड्स कमांड्स हैं जो बाहरी कमांड्स के समान व्यवहार करते हैं, लेकिन शेल में लागू होते हैं (इसलिए cdकोर्यूटिल्स का हिस्सा नहीं है)। यह कमांड को शेल की स्थिति को बदलने की अनुमति देता है, इस मामले में कॉल chdir()देखें (देखें man 2 chdir);

के बारे में which

अब, शीर्षक प्रश्न का उत्तर आसान है:
निष्पादन योग्य कमांड whichहमें यह नहीं बता सकता है कि सीडी एक अंतर्निहित कमांड है क्योंकि एक निष्पादन योग्य कमांड बिल्डरों के बारे में कुछ भी नहीं जानता है।

विकल्प type -a

एक विकल्प के रूप में which, आप उपयोग कर सकते हैं type -a; यह निष्पादन योग्य कमांड और बिल्डिंस देख सकता है; इसके अतिरिक्त, यह उपनाम और कार्यों को देखता है - शेल में भी लागू किया गया है:

$ type -a cd
cd is a shell builtin
$ type -a type
type is a shell builtin
$ type -a which
which is /usr/bin/which
which is /bin/which

1
महान व्याख्या!
साल्वनट्स

3
वर्तमान में स्वीकृत उत्तर की तुलना में बहुत बेहतर है - यह बताता है कि cd शेल बिलिन क्यों है।
लिली चुंग

28

cdएक POSIX- अनिवार्य शेल बिलिन है:

यदि एक साधारण आदेश में आदेश नाम और तर्कों की एक वैकल्पिक सूची होती है, तो निम्नलिखित क्रियाएं की जाएंगी:

  1. यदि कमांड नाम में कोई स्लैश नहीं है, तो निम्नलिखित अनुक्रम में पहला सफल कदम होगा:
    ...
    • यदि कमांड नाम निम्न तालिका में सूचीबद्ध उपयोगिता के नाम से मेल खाता है, तो उस उपयोगिता को लागू किया जाएगा।
      ...
      cd
      ... ...
    • अन्यथा, PATH का उपयोग करने के लिए आदेश खोजा जाएगा ...

हालांकि यह स्पष्ट रूप से यह नहीं कहता है कि यह बिल्ट-इन होना है, विवरण में कहा गया हैcd :

चूंकि सीडी वर्तमान शेल निष्पादन वातावरण को प्रभावित करता है, इसलिए इसे हमेशा एक शेल रेगुलर बिल्ट-इन के रूप में प्रदान किया जाता है।

से bashमैनुअल :

निम्नलिखित शेल बिलिन कमांड बॉर्न शेल से विरासत में मिले हैं। ये आदेश POSIX मानक द्वारा निर्दिष्ट के रूप में कार्यान्वित किए जाते हैं।
...

cd
       cd [-L|[-P [-e]]] [directory]

मुझे लगता है कि आप एक आर्किटेक्चर के बारे में सोच सकते हैं जहां cdएक बिल्डिन होना जरूरी नहीं है। हालाँकि, आपको यह देखना होगा कि अंतर्निहित अंतर्निहित क्या है। यदि आप कुछ कमांड के लिए कुछ करने के लिए शेल में विशेष कोड लिखते हैं, तो आप बिलिन होने के करीब पहुंच रहे हैं। जितना अधिक आप करते हैं, उतना ही बेहतर है कि बस एक बिल्डिन है।

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

या आपके पास एक cdप्रोग्राम हो सकता है जो chdirसिस्टम को कॉल करता है, और नए शेल पर लागू सभी मौजूदा पर्यावरण चर के साथ एक नया शेल शुरू करता है, और जब किया जाता है तब अपने मूल शेल (किसी तरह) को मारता है। 1

इससे भी बदतर, आपके पास एक प्रणाली भी हो सकती है जहां एक प्रक्रिया अन्य प्रक्रियाओं के वातावरण को बदल सकती है (मुझे लगता है कि तकनीकी रूप से आप डिबगर्स के साथ ऐसा कर सकते हैं)। हालांकि इस तरह की व्यवस्था बहुत, बहुत कमजोर होगी।

आप इस तरह के तरीकों को सुरक्षित करने के लिए अपने आप को अधिक से अधिक कोड जोड़ेंगे, और यह केवल एक बिलियन बनाने के लिए काफी सरल है।


यह एक निष्पादन योग्य है जो इसे एक बिलिन होने से नहीं रोकता है। इसका स्पष्ट उदाहरण:

echo तथा test

echoऔर testPOSIX- अनिवार्य उपयोगिताओं ( /bin/echoऔर /bin/test) हैं। फिर भी लगभग हर लोकप्रिय शेल में एक बिल्डिन echoऔर है test। इसी तरह, killयह भी बनाया गया है कि एक कार्यक्रम के रूप में उपलब्ध है। दूसरों में शामिल हैं:

  • sleep (सामान्य के रूप में नहीं)
  • time
  • false
  • true
  • printf

हालाँकि, कुछ मामले ऐसे होते हैं जहाँ एक कमांड कुछ भी नहीं हो सकता है लेकिन एक बिलिन है। उनमें से एक है cd। आमतौर पर, यदि पूर्ण पथ निर्दिष्ट नहीं है, और कमांड का नाम एक बिलिन से मेल खाता है, तो उस कमांड के अनुकूल फ़ंक्शन को कहा जाता है। शेल के आधार पर, बिलिन का व्यवहार और निष्पादन योग्य भिन्न हो सकता है (यह विशेष रूप से एक समस्या हैecho , जिसमें बेतहाशा भिन्न व्यवहार होते हैं । यदि आप व्यवहार के बारे में निश्चित होना चाहते हैं, तो निष्पादन योग्य का उपयोग करके कॉल करना बेहतर है। पूर्ण पथ, और सेट चर जैसे POSIXLY_CORRECT(फिर भी कोई वास्तविक गारंटी नहीं है)।

तकनीकी रूप से आपको ओएस प्रदान करने से रोकने वाला कुछ भी नहीं है जो एक शेल भी है और इसमें एक कमांड के रूप में प्रत्येक कमांड है। इस चरम छोर के करीब अखंड बिजीबॉक्स है । बिजीबॉक्स एक एकल बाइनरी है, जो (नाम के आधार पर जिसके साथ इसे कहा जाता है) एक 240 से अधिक कार्यक्रमों के रूप में व्यवहार कर सकता है , जिसमें एक अल्मक्विस्ट शेल ( ash) भी शामिल है। यदि आप PATHबिजीबॉक्स को चलाने के दौरान परेशान होते हैं ash, तो बिजीबॉक्स में उपलब्ध प्रोग्राम अभी भी आपके लिए निर्दिष्ट किए बिना सुलभ हैं PATH। वे शेल बिल्डिंस होने के करीब आते हैं, सिवाय इसके कि शेल ही एक प्रकार का बिलिन है जो बिजीबॉक्स के लिए है।


केस स्टडी: डेबियन अल्मक्विस्ट शेल ( dash)

यदि आप dashस्रोत को देखते हैं, तो निष्पादन थ्रेड कुछ इस तरह का होता है (बेशक, अतिरिक्त कार्यों के साथ जब पाइप और अन्य चीजों का उपयोग किया जाता है):

maincmdloopevaltreeevalcommand

evalcommandफिर findcommandयह निर्धारित करने के लिए उपयोग करता है कि कमांड क्या है। यदि यह एक बिलिन है, तो :

 case CMDBUILTIN:
     if (spclbltin > 0 || argc == 0) {
         poplocalvars(1);
         if (execcmd && argc > 1)
             listsetvar(varlist.list, VEXPORT);
     }
     if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
         if (exception == EXERROR && spclbltin <= 0) {
             FORCEINTON;
             break;

cmdentry.u.cmdएक struct( struct builtincmd), में से एक है, जिसके सदस्य एक समारोह सूचक है, एक हस्ताक्षर की खासियत के साथ main: (int, char **)evalbltinसमारोह कॉल (इसके आधार पर उस builtin है evalआदेश या नहीं) या तो evalcmd, या इस समारोह सूचक। वास्तविक कार्य विभिन्न स्रोत फ़ाइलों में परिभाषित किए गए हैं। echo, उदाहरण के लिए, है :

int
echocmd(int argc, char **argv)
{
    int nonl;

    nonl = *++argv ? equal(*argv, "-n") : 0;
    argv += nonl;

    do {
        int c;

        if (likely(*argv))
            nonl += print_escape_str("%s", NULL, NULL, *argv++);
        if (nonl > 0)
            break;

        c = *argv ? ' ' : '\n';
        out1c(c);
    } while (*argv);
    return 0;
}

इस खंड में स्रोत कोड के सभी लिंक लाइन नंबर-आधारित हैं, इसलिए वे बिना सूचना के बदल सकते हैं।


1 POSIX सिस्टम में एक cdनिष्पादन योग्य है


पक्षीय लेख:

यूनिक्स और लिनक्स पर बहुत सारे उत्कृष्ट पोस्ट हैं जो शेल व्यवहार से संबंधित हैं। विशेष रूप से:

यदि आपने अब तक सूचीबद्ध प्रश्नों में एक पैटर्न पर ध्यान नहीं दिया है, तो उनमें से लगभग सभी में स्टीफन चेज़लस शामिल हैं ।


4
ध्यान दें कि आप cdमदद पाठ के साथ help cd(सभी शेल बिल्ट कमांड के लिए एक ही चीज) प्राप्त कर सकते हैं
सिल्वेन पिनेउ

@ सिल्वेनपीन्यू भले ही मैं बैश मैनुअल से जुड़ा हो, लेकिन यह सलाह आम तौर पर अन्य गोले, जैसे कि ज़ीश पर लागू नहीं होती है।
मूरू

दरअसल helpएक बैश बिलिन (zsh, it के लिए run-help cd) है
सिल्वेन

POSIX विनिर्देश से जुड़ा हुआ विवरण स्पष्ट रूप से यह नहीं कहता है कि cdशेल में अंतर्निहित होना चाहिए ... लेकिन cdएक शेल-बिल्ट-इन के रूप में UNIX में प्रक्रिया गुण और उनका स्थानांतरण कैसे कार्य करता है, इसके आधार पर केवल सीधा कार्यान्वयन है। वोल्कर सीगल का उत्तर देखें ।
पाबौक

@pabouk वास्तव में (इसे उपयोगिता कहते हैं), और फिर आगे कहते हैं: "चूंकि सीडी वर्तमान शेल निष्पादन वातावरण को प्रभावित करता है, इसलिए इसे हमेशा एक शेल रेगुलर बिल्ट-इन के रूप में प्रदान किया जाता है।"
मूरू

8

आप के लिए एक निष्पादन योग्य नहीं मिल सकता है cdक्योंकि कोई भी नहीं है।

cdआपके शेल (जैसे bash) का एक आंतरिक कमांड है ।


7

से man which:

जो फ़ाइलों (या लिंक) के पथनाम को लौटाता है, जिसे वर्तमान परिवेश में निष्पादित किया जाएगा, इसके तर्क एक सख्त POSIX-अनुरूप शेल में कमांड के रूप में दिए गए थे। यह तर्कों के नाम से मेल खाती निष्पादन योग्य फ़ाइलों के लिए PATH की खोज करके करता है। यह प्रतीकात्मक लिंक का पालन नहीं करता है।

जैसा कि हम वर्णन से देख सकते हैं which, यह केवल जाँच है PATH। इसलिए यदि आपने कुछ लागू किया है bash function, तो यह आपको कुछ नहीं दिखाएगा। साथ में कमांड का उपयोग करना बेहतर है ।typewhich

उदाहरण के लिए उबंटू lsकमान में उर्फ ls --color=auto

$ type ls
ls is aliased to `ls --color=auto'

$ which ls
/bin/ls

और यदि आप परीक्षण समारोह को लागू करते हैं hello:

$ function hello() { for i in {1,2,3}; do echo Hello $i;done }
$ which hello

whichकुछ नहीं दिखाता। लेकिन type:

$ type hello
hello is a function
hello () 
{ 
    for i in {1,2,3};
    do
        echo Hello $i;
    done
}

आपके मामले में:

$ type cd
cd is a shell builtin

इसका मतलब है कि cdएक शेल बिलिन है , यह अंदर है bashman bashसेक्शन शेल बिल्डिंग्स कमेंड्स में वर्णित सभी बैश बिल्डिंग्स

SHELL BUILTIN COMMANDS
       Unless otherwise noted, each builtin command documented in this section
       as accepting options preceded by - accepts -- to signify the end of the
       options.   The  :, true, false, and test builtins do not accept options
       and do not treat -- specially.  The exit, logout, break, continue, let,
       and  shift builtins accept and process arguments beginning with - with‐
       out requiring --.  Other builtins that accept  arguments  but  are  not
       specified  as accepting options interpret arguments beginning with - as
       invalid options and require -- to prevent this interpretation.


1
यह शायद अधिक जोर दिया जाना चाहिए: उपयोग न करें which, उपयोग करें type
ट्रिपलए
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.