मेरे कार्यक्रम को "सेट" क्यों नहीं कहा जाता है?


10

मैंने एक सरल सी प्रोग्राम बनाया है जैसे:

int main(int argc, char *argv[]) {

    if (argc != 5) {
       fputs("Not enough arguments!\n", stderr);
       exit(EXIT_FAILURE);
    }

और मैं अपने पेट में आदि / bash.bashrc की तरह संशोधित किया है:

PATH=.:$PATH

मैंने इस प्रोग्राम को set.c के रूप में सहेजा है और इसे संकलित कर रहा हूं

gcc -o set set.c

फ़ोल्डर में

~/Programming/so

हालांकि, जब मैं फोन करता हूं

set 2 3

कुछ नहीं हुआ। ऐसा कोई पाठ नहीं है जो प्रकट होता है।

कॉलिंग

./set 2 3

अपेक्षित परिणाम देता है

मुझे पहले कभी पाथ के साथ कोई समस्या नहीं हुई है और

which set

लौटता है ./set। तो ऐसा लगता है कि पथ सही है। क्या हो रहा है?


10
इसे जोड़ना अपेक्षाकृत खतरनाक है। ' अपने पेट को बेहतर उपयोग करने के लिए ।/ स्थानीय निर्देशिका से कुछ निष्पादित करते समय, या निष्पादन योग्य को एक अच्छी तरह से ज्ञात निर्देशिका में स्थानांतरित करें जैसे ~ / bin /
TREE

7
testमूल रूप से उसी कारण से अपने परीक्षण कार्यक्रम को कॉल करना भी एक बुरा विचार है ; testएक शेल भी बनाया गया है।
जोनाथन लेफ्लर

@JonathanLeffler और फिर भी त्वरित परीक्षणों के लिए एक कार्यक्रम को बुलाकर testसमझ में आता है। बेशक जब तक आप इसे अपने PATHपास रखते हैं तब तक आपको वास्तव में एक अलग नाम के साथ आना चाहिए था। और जब तक आप कार्यक्रम को अपने अंदर नहीं रखते हैं तब तक आपको PATHइसे ./testवैसे ही लागू करना होगा । इसलिए testकिसी प्रोग्राम के लिए नाम का उपयोग करना ठीक है क्योंकि यह एक त्वरित परीक्षा है जिसे आप दिन के अंत से पहले हटाने का इरादा रखते हैं।
कास्परड

1
@kasperd: जहां तक ​​मुझे जानकारी है, एक त्वरित परीक्षण कार्यक्रम के लिए पारंपरिक नाम है foo
हमखोलम ने मोनिका

यदि आप इसे नाम देते हैं lsतो जब भी आप यह देखने के लिए जाते हैं कि यह मौजूद है तो यह चलेगा (लेकिन केवल यदि आप अपना रास्ता संशोधित करते हैं जैसा कि आपने प्रश्न में किया था)।
ctrl-alt-delor

जवाबों:


24

उपयोग करने के बजाय which, जो तब काम नहीं करता है जब आपको इसकी सबसे अधिक आवश्यकता होती है , यहtype निर्धारित करने के लिए उपयोग करें कि जब आप एक कमांड टाइप करेंगे तो क्या होगा:

$ which set
./set
$ type set
set is a shell builtin

शेल हमेशा खोज से पहले बिल्डरों की तलाश करता है $PATH, इसलिए सेटिंग $PATHयहां मदद नहीं करती है।

अपने निष्पादन योग्य का नाम किसी और चीज़ में बदलना सबसे अच्छा होगा, लेकिन यदि आपके असाइनमेंट को प्रोग्राम का नाम देना है set, तो आप एक शेल का उपयोग कर सकते हैं:

$ function set { ./set; }
$ type set
set is a function
set ()
{
    ./set
}

(यह काम करता है bash, लेकिन अन्य गोले kshइसे अनुमति नहीं दे सकते हैं। अधिक पोर्टेबल समाधान के लिए माइकर्सव का जवाब देखें।)

अब टाइपिंग set"सेट" नाम के फ़ंक्शन को चलाएगा, जो निष्पादित करता है ./set। जीएनयू bashबिल्डरों की तलाश से पहले कार्यों की तलाश करता है, और यह खोज से पहले बिल्डरों की तलाश करता है $PATH। Bash man पेज में "COMMAND EXECUTION" नाम का सेक्शन इस पर अधिक जानकारी देता है।

दस्तावेज़ को भी देखें builtinऔर command: help builtinऔर help command


3
आप सलाह देते typeहैं which, लेकिन कोई कारण न दें। ( मुझे पता है क्यों , लेकिन किसी को सिफारिश की जरूरत नहीं होगी।)
cjm

1
@cjm यहाँ पर एक पूरा ग्रंथ है क्यों नहीं जो : unix.stackexchange.com/questions/85249/...
एंथोनी Geoghegan

बहुत सूचनाप्रद। आप कभी भी अनुमान नहीं लगा सकते हैं कि इस तरह के एक साधारण से आदेश पर इतना विवाद है जो एक साधारण कार्य करता है
गणेश आंद्रेई

4
@GaneaDanAndrei मुख्य रूप से, typeइसके बजाय का उपयोग करें which, अपने प्रोग्राम को "सेट" नाम न दें, और महसूस करें कि function set { ./set; }यह एक बदसूरत हैक है जिसे आपको शायद बचना चाहिए।
पीलेतन्फ़िल

11

setबैश में एक बिलिन है (और शायद सबसे अन्य गोले)। इसका मतलब है कि फंक्शन की तलाश में बैश भी रास्ता नहीं खोजेगा।

एक पक्ष की टिप्पणी के रूप में, मैं .सुरक्षा कारणों से रास्ते में जोड़ने के खिलाफ दृढ़ता से सलाह दूंगा। किसी अन्य उपयोगकर्ता द्वारा निष्पादन योग्य फ़ाइल जोड़ने cdके /tmpबाद उदाहरण के लिए आईएनजी से बाहर निकलने की कल्पना करें /tmp/cd


2
हाँ, यह एक बेवकूफ विचार है कि आदेश में पर मेरे शिक्षक बलों के लिए ,, नहीं अव्यवसायिक एक कार्यक्रम 'पेश करने के दौरान देखने के लिए वह ग्रेड आप नीचे अगर यह नहीं किया जाता
Ganea दान आंद्रेई

1
ब्राउनी महान शिक्षकों के लिए इंगित करता है :(
क्लीम्परजिस्ट

4
cdएक शेल बिल्ट-इन है, इसलिए उदाहरण उसी कारण से काम नहीं करेगा जैसे कि set
एमिल जेकाबेक

15
का उपयोग करते हुए ./fooएक कार्यक्रम को लागू करने की है पेशेवर; यह दर्शाता है कि आप समझते हैं कि .$ PATH में क्यों नहीं होना चाहिए। आपका शिक्षक गलत है, और आप उसे बता सकते हैं कि मैंने ऐसा कहा।
zwol

10

setनहीं है तो बस एक builtin, यह एक है POSIX विशेष builtin । कुछ अंतर्निहित आदेशों जो मानकों द्वारा निर्दिष्ट कुछ और करने से पहले एक आदेश खोज में पाया जा सकता है कर रहे हैं - $PATHकी खोज नहीं है, समारोह के नाम की खोज नहीं कर रहे हैं, और आदि अधिकांश builtins जो कर रहे हैं नहीं विशेष वास्तव में कर रहे हैं की आवश्यकता POSIX मानक से होने के लिए शेल $PATH से पहले अपने में पाया किसी भी अपनी स्वयं की निर्मित प्रक्रियाओं को चलाएगा। इस का सच है echoऔर सबसे दूसरों (हालांकि मानक इस संबंध में सम्मानित किया है अतीत में खुला समूह मेलिंग सूची पर विवाद का एक मामला आ चुका है,) , लेकिन नहीं की set, trap, break,return, continue, ., :, times, eval, exit, export, readonly, unset, या exec

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

हालांकि, यदि आप इसे आक्रमण करने की इच्छा रखते हैं, तो आप ऐसा कर सकते हैं alias। शेल विस्तार का क्रम इस कार्य को सक्षम बनाता है। क्योंकि aliasकमांड पढ़ा जा रहा है, इसलिए इसका विस्तार किया गया है, जो भी आप setअपनी परिभाषा में नाम की जगह लेते हैं , वह सही तरीके से विस्तार करेगा, यह संभवतः उन नामों में से एक का विस्तार नहीं होना चाहिए।

तो आप कर सकते हैं:

alias set=./set

... जो ठीक काम करेगा।


3

समस्या यह है कि setएक शेल बिल्डिन है और सबसे अच्छा उपाय यह होगा कि आप अपने निष्पादन योग्य प्रोग्राम के लिए एक अलग नाम का उपयोग करें।

संयोग से, पिछले हफ्ते, मैंने एक ही नाम के साथ शेल बिल्डरों के बजाय सिस्टम कमांड को चलाने के तरीके पर एक सवाल पूछा था और मैंने जो समाधान स्वीकार किया था, वह था env:

env set 2 3

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

./set 2 3

उपरोक्त दोनों उपाय शेल एग्नोस्टिक हैं, अर्थात, वे इस बात पर ध्यान दिए बिना काम करेंगे कि आप किस शेल का उपयोग कर रहे हैं।

commandबिलिन का उपयोग करने जैसे सुझाव बाश में काम नहीं करेंगे: यह केवल शेल कार्यों को चलाने से रोकता है । हालांकि, यह प्रलेखित नहीं है, मैंने यह भी देखा है कि commandशेल कीवर्ड का उपयोग करना भी है । हालांकि, यह खोल के लिए एक ही काम नहीं चलेगा builtins जैसे set। जैसा कि मैं इसे समझता हूं, commandअन्य गोले जैसे zsh के साथ काम कर सकता है।

इसके अलावा, इस तरह के रूप चाल \setया "set"या 'set'बैश builtins लिए काम नहीं करते - हालांकि वे के बजाय निष्पादन योग्य फ़ाइलों को चलाने के लिए उपयोगी होते हैं उपनाम या खोल कीवर्ड

नोट: यह उत्तर मूल रूप से एरिक (स्वीकृत) उत्तर पर एक टिप्पणी के रूप में शुरू हुआ, लेकिन एक टिप्पणी में फिट होने के लिए बहुत बड़ा हो गया। पैथ को typeजोड़ने और न जोड़ने की सिफारिश करने वाले अन्य उत्तर .अच्छे हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.