मेकफाइल में मैं 'cd' कमांड कैसे लिखूं?


354

उदाहरण के लिए, मेरे मेकफाइल में ऐसा कुछ है:

all:
     cd some_directory

लेकिन जब मैंने टाइप किया तो मैंने कमांड makeमें केवल 'cd some_directory' को देखा echo


5
यह स्पष्ट नहीं है कि आप क्या करना चाहते हैं, लेकिन, अपने अनुभव में make, मैं कभी इस तरह निर्देशिका को बदलना नहीं चाहता था। शायद आपको अपने समाधान के लिए एक और दृष्टिकोण की कोशिश करनी चाहिए?
पी। शेव्ड

2
आपकी निर्देशिका महत्वपूर्ण है यह मानना ​​एक सामान्य नौसिखिया गलती है। ज्यादातर चीजों के लिए यह नहीं है; cd dir; cmd fileलगभग हमेशा अधिक उपयोगी के रूप में व्यक्त किया जा सकता है cmd dir/file
ट्रिपल

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

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

जवाबों:


620

यह वास्तव में कमांड को निष्पादित कर रहा है, निर्देशिका को बदलकर some_directory, हालांकि, यह एक सब-प्रोसेस शेल में किया जाता है, और आप जिस शेल से काम कर रहे हैं उसे न तो बनाते हैं और न ही प्रभावित करते हैं।

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

उदाहरण के लिए:

all:
        cd some_dir; echo "I'm in some_dir"; \
          gcc -Wall -o myTest myTest.c

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

all:
        cd some_dir && echo "I'm in some_dir" && \
          gcc -Wall -o myTest myTest.c

विनाशकारी काम करते समय यह विशेष रूप से महत्वपूर्ण है, जैसे कि सफाई, जैसा कि आप अन्यथा गलत सामान को नष्ट कर देंगे, ऐसा होना चाहिए cd जो भी कारण के लिए विफल ।

हालांकि, उप-निर्देशिका में कॉल करने के लिए एक सामान्य उपयोग है, जिसे आप देखना चाहते हैं। इसके लिए एक कमांड लाइन विकल्प है, ताकि आपको cdखुद को कॉल न करना पड़े , इसलिए आपका नियम इस तरह दिखाई देगा

all:
        $(MAKE) -C some_dir all

जो "सभी" लक्ष्य के साथ वहाँ बदल जाएगा some_dirऔर Makefileवहाँ पर अमल करेगा । सर्वोत्तम अभ्यास के रूप में, सीधे $(MAKE)कॉल करने के बजाय उपयोग करें make, क्योंकि यह सही मेक इंस्टेंस को कॉल करने के लिए ध्यान रखेगा (यदि आप, उदाहरण के लिए, अपने बिल्ड वातावरण के लिए एक विशेष मेक संस्करण का उपयोग करें), और साथ ही साथ चलने पर थोड़ा अलग व्यवहार प्रदान करें कुछ स्विच का उपयोग करना, जैसे कि -t

रिकॉर्ड के लिए, इसे हमेशा निष्पादित करें कमांड को निष्पादित करें (जब तक कि स्पष्ट रूप से दबाया न जाए), भले ही इसका कोई आउटपुट न हो, जो कि आप देख रहे हैं।


8
खैर, हमेशा नहीं । प्रतिध्वनि को दबाने के लिए, लाइन की शुरुआत में @ डाल दें।
बीटा

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

46
दो एनआईटी: 1. कमांड को वास्तव में शामिल होना चाहिए &&, क्योंकि ;यदि निर्देशिका मौजूद नहीं है और cdविफल रहता है, तो शेल शेष कमांड को चालू निर्देशिका में चालू रखेगा, जो रहस्यमयी जैसी चीजों का कारण बन सकता है "फाइल नहीं पाया "संकलित करने के लिए संदेश, अनंत लूप जब बनाते हैं, या नियमों जैसे आपदा के लिए clean:: cd dir; rm -rf *। 2. सब-मेक इनवॉइस करते समय, $(MAKE)इसके बजाय कॉल करें makeताकि विकल्प सही तरीके से पास हो जाएं
andrewdotn

2
@perreal, मैं आमतौर पर एक पैटर्न नियम को इस तरह परिभाषित करता हूं: %-recursive:शरीर के साथ: @T="$@";$(MAKE) -C some_dir $${T%-*}(मेरे पास आमतौर पर फॉर-लूप है, उप-सूची की सूची पर लूप करने के लिए, $${T%-*}एक बैश विस्तार है जो -recursiveलक्ष्य नाम के हिस्से को हटाता है ) और फिर प्रत्येक के लिए स्पष्ट शॉर्ट हाथ (और .PHONY) के लक्ष्यों को परिभाषित करते हैं, जैसे all: all-recursive, check: check-recursive, clean: clean-recursive
फाल्स्ट्रो

1
@ChristianStewart, सच है, जैसा कि टिप्पणी 2 और 3 में उल्लेख किया गया था
फालस्ट्रो

94

GNU मेक 3.82 (जुलाई 2010) से शुरू करके , आप .ONESHELLशेल के एक पल में सभी रेसिपी लाइनों को चलाने के लिए विशेष लक्ष्य का उपयोग कर सकते हैं (बोल्ड जोर मेरा):

  • नई विशेष लक्ष्य: .ONESHELLका निर्देश बनाने के आह्वान करने के लिए खोल का एक उदाहरण और साथ इसे प्रदान पूरे नुस्खा परवाह किए बिना यह कितने रेखाएं हों, की,। [...]
.ONESHELL: # Only applies to all target
all:
    cd ~/some_dir
    pwd # Prints ~/some_dir if cd succeeded

6
बस ध्यान दें कि pwdखुद के साथ ही काम करता है, `pwd`(बैकटिक साथ), लेकिन $(shell pwd)और $(PWD)अभी भी करने से पहले निर्देशिका वापस आ जाएगी cdआदेश, ताकि आप उन्हें सीधे उपयोग नहीं कर सकते।
अनिल

3
हाँ, क्योंकि चर और समारोह विस्तार, मेकअप द्वारा आदेशों को क्रियान्वित करने से पहले किया जाता है, जबकि pwdऔर `pwd`खोल से ही मार डाला जाता है।
चन्नोस

2
हर कोई विरासत मेकफाइल्स पर काम नहीं करता है, और फिर भी यह उत्तर जानने के बारे में है कि यह संभावना मौजूद है।
चन्नोस

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

1
सेट SHELLFLAGSकरने के लिए -e -cऔर खोल पहले आदेश है कि विफल रहता है पर बाहर निकल जाएगा।
टिमोथी बाल्डविन

21

निर्देशिकाओं से निपटने और बनाने के लिए यहां एक सुंदर ट्रिक है। मल्टीलाइन स्ट्रिंग्स, या "सीडी;" प्रत्येक कमांड पर, एक साधारण chdir फंक्शन को परिभाषित करें:

CHDIR_SHELL := $(SHELL)
define chdir
   $(eval _D=$(firstword $(1) $(@D)))
   $(info $(MAKE): cd $(_D)) $(eval SHELL = cd $(_D); $(CHDIR_SHELL))
endef

फिर आपको बस इतना करना है कि इसे अपने नियम में कॉल करें:

all:
          $(call chdir,some_dir)
          echo "I'm now always in some_dir"
          gcc -Wall -o myTest myTest.c

आप निम्न कार्य भी कर सकते हैं:

some_dir/myTest:
          $(call chdir)
          echo "I'm now always in some_dir"
          gcc -Wall -o myTest myTest.c

41
"प्यारा"? पैर में खुद को गोली मारने के लिए पर्याप्त रस्सी की तरह।
ट्रिपल

1
क्या यह वर्तमान निर्देशिका तब उस नियम में, या बाद के सभी निष्पादित नियमों के लिए निर्धारित है? इसके अलावा, क्या विंडोज के तहत इस काम में कुछ बदलाव होगा?
user117529

8
यह निश्चित रूप से समानांतर निष्पादन ( -jn) के लिए टूटता है , जो वास्तव में बनाने का पूरा बिंदु है ।
बोब्बोगो

5
यह एक खराब हैक है। अगर आपको कभी ऐसी चीज का सहारा लेना है, तो आप इसके लिए मेकफाइल्स का उपयोग नहीं कर रहे हैं।
गैटोपिच

4
मैं इससे सहमत नहीं हूँ कि इसकी खराब हैक सुनिश्चित है। लेकिन कुछ दुष्ट चीजों को प्रदर्शित करता है जो आप कर सकते हैं।
जोस

9

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

GNU मेक के साथ, आप कुछ ऐसा कर सकते हैं:

BIN=/bin
foo:
    $(shell cd $(BIN); ls)

5
क्यों या $(shell ...)कब (जैसा @andrewdotn ने बताया) काफी होगा। cd $(BIN); lscd $(BIN) && ls
वाष्प

1

दिर बदलने के लिए

foo: 
    $(MAKE) -C mydir

multi:
    $(MAKE) -C / -C my-custom-dir   ## Equivalent to /my-custom-dir

-6

ऐशे ही:

target:
    $(shell cd ....); \
    # ... commands execution in this directory
    # ... no need to go back (using "cd -" or so)
    # ... next target will be automatically in prev dir

सौभाग्य!


1
नहीं, यह गलत है। विशेष रूप से, $(shell cd ....)निष्पादित किया जाता है जब मेकफाइल शुरू में पार्स किया जाता है, न कि जब यह विशेष नुस्खा चलाया जाता है।
ट्रिपलए

@triplee काफी नहीं है - $(shell)केवल तब विस्तार किया जाता है जब लक्ष्य बनाने का निर्णय लेते हैं । तो मेकअप नुस्खा की जरूरत कभी नहीं, यह इसके विस्तार नहीं होंगे।
बोबोगो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.