क्यों स्रोत lib / * काम नहीं करता है?


11

मेरे पास एक छोटा प्रोग्राम है जिसमें निम्नलिखित फ़ोल्डर संरचना शामिल है:

- main.sh
- lib/
  - clean.sh
  - get.sh
  - index.sh
  - test.sh

प्रत्येक फ़ाइल में एक एकल फ़ंक्शन होता है जिसका मैं उपयोग करता हूं main.sh

main.sh:

source lib/*

get_products
clean_products
make_index
test_index

ऊपर के पहले दो कार्य काम करते हैं लेकिन दूसरे दो नहीं।

फिर भी अगर मैं इसके source lib/*साथ प्रतिस्थापित करता हूं :

source lib/get.sh
source lib/clean.sh
source lib/index.sh
source lib/test.sh

सब कुछ उम्मीद के मुताबिक काम करता है।

किसी को पता है कि source lib/*उम्मीद के मुताबिक काम क्यों नहीं होता है?


2
प्रश्न का उत्तर नहीं, यदि आप इसे एक-लाइनर में करना चाहते हैं, तो यह देखें /etc/bashrcकि इससे forनिपटने के लिए यह लूप का उपयोग कैसे करता है /etc/profile.d/*.sh। अगर आपको भरोसा है कि इसकी सामग्री lib/को एक लाइनर में कम किया जा सकता है:for i in lib/*.sh; do . "$i"; done
रिच

जवाबों:


21

बैश के sourceबिलिन केवल एक ही फ़ाइल नाम लेता है:

source filename [arguments]

पहले पैरामीटर से परे कुछ भी करने के लिए एक स्थितीय पैरामीटर बन जाता है filename

एक साधारण चित्रण:

$ cat myfile
echo "param1: $1"
$ source myfile foo
param1: foo

का पूर्ण उत्पादन help source

source: source filename [arguments]

Execute commands from a file in the current shell.

Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.

(यह समतुल्य "डॉट सोर्स" बिलिन पर भी लागू होता है, .जो ध्यान देने योग्य है, पोसिक्स तरीका है और इस तरह यह बहुत ही पोर्टेबल है।)

प्रतीत होता है विरोधाभासी व्यवहार के रूप में आप देख रहे हैं आप करने के बाद main.sh चलाने की कोशिश कर सकते हैं set -x। यह देखते हुए कि किन बयानों पर अमल हो रहा है और कब कोई सुराग मिल सकता है।


7

बैश प्रलेखन इंगित करता है कि sourceएक एकल फ़ाइलनाम पर काम करता है :

। (एक अवधि)

फ़ाइल नाम [तर्क]

वर्तमान शेल संदर्भ में फ़ाइल नाम तर्क से आदेशों को पढ़ें और निष्पादित करें । यदि फ़ाइल नाम ...

और स्रोत कोड ... के लिए स्रोत ... इस बैकअप लेता है:

result = source_file (filename, (list && list->next));

कॉल करने के लिए कहां source_fileपरिभाषित किया evalfile.cगया है _evalfile:

rval = _evalfile (filename, flags);

और _evalfileकेवल एक फ़ाइल खोलता है:

fd = open (filename, O_RDONLY);

5

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

जब आप नीचे करते हैं तो एक फ़ाइल की संभावना होती है ( .shएक्सटेंशन नहीं ) बस एक अस्थायी फ़ाइल होती है जिसमें कुछ हानिकारक कमांड होते हैं (जैसे rm -rf *) जिसे निष्पादित किया जा सकता है (यह मानते हुए कि उनके पास अनुमति निष्पादित है)

source lib/*

तो हमेशा उचित बाउंड सेट के साथ ग्लोब का विस्तार करें, अपने मामले में हालांकि आप केवल *.shफाइलों पर अकेले लूप कर सकते हैं

for globFile in lib/*.sh; do
    [ -f "$globFile" ] || continue
    source "$globFile"
done

यहाँ [ -f "$globFile" ] || continueकी देखभाल लूप के लौटने बाहर ले अगर कोई ग्लोब पैटर्न वर्तमान फ़ोल्डर यानी विस्तारित खोल विकल्पों में से बराबर में से मेल खाता होगा nullglobमें bashखोल।


प्रक्रिया प्रतिस्थापन के साथ प्रयोग catकरना भी काम करेगा:source <(cat lib/*.sh)
Xophmeister

@Xophmeister, ... "काम" के लिए अधिक सीमित मूल्य के लिए। आप के साथ डिबग करने का प्रयास किया set -xहै और एक PS4डालता है BASH_SOURCEऔर LINENOअपने लॉग में, आप अब जो फ़ाइल देख सकते हैं और लाइन किसी दिए गए आदेश से आता है हो सकता है।
चार्ल्स डफी

2
@Xophmeister, ... भी, एक स्क्रिप्ट इसके निष्पादन को शॉर्ट-सर्किट कर सकती है return। उस अभ्यास का पालन करते हुए, कोई भी स्क्रिप्ट जो सभी निम्नलिखित को क्रियान्वित करने से रोकती है ।
चार्ल्स डफी

1
/etc/bashrcजब यह प्रक्रिया करता है तो यह बहुत करीब है /etc/profile.d/*.sh
रिच

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