अन्य लिपियों को शामिल करने के लिए सबसे अच्छा कैसे?


353

जिस तरह से आप आम तौर पर एक स्क्रिप्ट शामिल करेंगे वह "स्रोत" के साथ है

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

main.sh:

#!/bin/bash

source incl.sh

echo "The main script"

incl.sh:

echo "The included script"

"./Main.sh" निष्पादित करने का आउटपुट है:

The included script
The main script

... अब, यदि आप उस शेल स्क्रिप्ट को किसी अन्य स्थान से निष्पादित करने का प्रयास करते हैं, तो यह तब तक शामिल नहीं हो सकता जब तक कि यह आपके पथ में न हो।

यह सुनिश्चित करने का एक अच्छा तरीका है कि आपकी स्क्रिप्ट में शामिल स्क्रिप्ट मिल सकती है, खासकर अगर उदाहरण के लिए, स्क्रिप्ट को पोर्टेबल होने की आवश्यकता है?


2
इसे एक देखें: stackoverflow.com/questions/59895/…
Lluís

1
आपका प्रश्न इतना अच्छा और ज्ञानवर्धक है कि आपके प्रश्न को पूछने से पहले ही मेरे प्रश्न का उत्तर दे दिया गया था ! अच्छी नौकरी!
गेब्रियल स्टेपल्स

जवाबों:


229

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

#!/bin/sh

my_dir="$(dirname "$0")"

"$my_dir/other_script.sh"

5
यदि स्क्रिप्ट $ PATH के माध्यम से निष्पादित की जाती है तो यह काम नहीं करेगा। तब which $0उपयोगी होगा
ह्यूगो

41
शेल स्क्रिप्ट के स्थान को निर्धारित करने का कोई विश्वसनीय तरीका नहीं है, mywiki.wooledge.org/BashFAQ/028
फिलिप

12
@Philipp, उस प्रविष्टि का लेखक सही है, यह जटिल है, और इसमें गोचर्स हैं। लेकिन यह कुछ प्रमुख बिंदुओं को याद कर रहा है, सबसे पहले, लेखक आपके बारे में बहुत सारी बातें मानता है कि आप अपनी बैश स्क्रिप्ट के साथ क्या करने जा रहे हैं। मैं एक अजगर स्क्रिप्ट के बिना चलने की उम्मीद नहीं करेगा यह निर्भरता के बिना भी है। बैश एक गोंद भाषा है जो आपको जल्दी से चीजें करने की अनुमति देती है जो अन्यथा कठिन होगी। जब आपको काम करने के लिए अपनी निर्माण प्रणाली की आवश्यकता होती है, तो व्यावहारिकता (और स्क्रिप्ट के बारे में एक अच्छी चेतावनी निर्भरता को खोजने में सक्षम नहीं) जीतती है।
आरोन एच।

11
बस BASH_SOURCEसरणी के बारे में सीखा है , और इस सरणी में पहला तत्व हमेशा वर्तमान स्रोत को कैसे इंगित करता है।
haridsv

6
यदि स्क्रिप्ट अलग-अलग स्थान हैं, तो यह काम नहीं करेगा। जैसे /home/me/main.sh कॉल /home/me/test/inc.sh जैसे dirname वापस आएगा / घर / मुझे। sacii उत्तर BASH_SOURCE का उपयोग करके एक बेहतर समाधान है stackoverflow.com/a/12694189/1000011
ऑप्टिकक्लोग्राम

187

मुझे पता है कि मुझे पार्टी में देरी हो रही है, लेकिन इससे कोई फर्क नहीं पड़ता कि आप स्क्रिप्ट कैसे शुरू करते हैं और विशेष रूप से बिलिन का उपयोग करते हैं:

DIR="${BASH_SOURCE%/*}"
if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
. "$DIR/incl.sh"
. "$DIR/main.sh"

. (डॉट) कमांड एक उपनाम है source , $PWDवर्किंग डायरेक्टरी के लिए पथ है, BASH_SOURCEएक सरणी चर है, जिसके सदस्य स्रोत फ़ाइलनाम हैं, ${string%substring}$ स्ट्रिंग के पीछे से $ सबस्ट्रिंग का सबसे छोटा मैच स्ट्रिप्स।


7
थ्रेड में यह एकमात्र उत्तर है जो लगातार मेरे लिए काम करता है
जस्टिन

3
@sacii मुझे पता है कि लाइन की if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fiआवश्यकता कब है ? अगर कमांड को चलाने के लिए बैश करने के लिए चिपकाया जा रहा है तो मुझे इसकी आवश्यकता पड़ सकती है। हालाँकि, अगर कोई स्क्रिप्ट फ़ाइल संदर्भ के अंदर चल रही है, तो मुझे इसकी आवश्यकता नहीं दिख रही है ...
जॉनी वोंग

2
यह भी ध्यान देने योग्य है कि यह कई sourceएस के अनुसार अपेक्षित रूप से काम करता है (मेरा मतलब है, यदि आप sourceएक स्क्रिप्ट है जो sourceकिसी अन्य निर्देशिका में है और इसी तरह, यह अभी भी काम करता है)।
सीरो कोस्टा

4
यह नहीं होना चाहिए ${BASH_SOURCE[0]}क्योंकि आप केवल नवीनतम बुलाया चाहते हैं? इसके अलावा, उपयोग DIR=$(dirname ${BASH_SOURCE[0]})करने से आप
इफ

1
क्या आप इस स्निपेट को बिना किसी आवश्यक लाइसेंस के CC0 की तरह उपलब्ध कराना चाहते हैं या इसे सार्वजनिक डोमेन में जारी करना चाहते हैं? मैं इस शब्दशः का उपयोग करना चाहता हूं, लेकिन हर एक स्क्रिप्ट के शीर्ष पर रोपण डालने के लिए यह कष्टप्रद है!
BeeOnRope

52

के लिए एक विकल्प:

scriptPath=$(dirname $0)

है:

scriptPath=${0%/*}

.. dirname पर निर्भरता नहीं होने का फायदा, जो एक अंतर्निहित कमांड नहीं है (और हमेशा एमुलेटर में उपलब्ध नहीं है)


2
basePath=$(dirname $0)जब स्क्रिप्ट फ़ाइल सॉर्ट की जाती है तो मुझे रिक्त मान दिया जाता है।
प्रयागपाद

41

यदि यह उसी निर्देशिका में है, जिसका आप उपयोग कर सकते हैं dirname $0:

#!/bin/bash

source $(dirname $0)/incl.sh

echo "The main script"

2
दो नुकसान: 1) $0है ./t.shऔर dirname रिटर्न .; 2) cd binवापसी के बाद .सही नहीं है। $BASH_SOURCEकोई बेहतर नहीं है।
18446744073709551615

एक और नुकसान: निर्देशिका नाम में रिक्त स्थान के साथ यह प्रयास करें।
ह्यूबर्ट ग्रौस्सोवाकियाक

source "$(dirname $0)/incl.sh"उन मामलों के लिए काम करता है
डीएसएम

27

मुझे लगता है कि ऐसा करने का सबसे अच्छा तरीका क्रिस बोरान के तरीके का उपयोग करना है, लेकिन आपको इस तरह से MY_DIR की गणना करनी चाहिए:

#!/bin/sh
MY_DIR=$(dirname $(readlink -f $0))
$MY_DIR/other_script.sh

पढ़ने के लिए आदमी पृष्ठों को उद्धृत करने के लिए:

readlink - display value of a symbolic link

...

  -f, --canonicalize
        canonicalize  by following every symlink in every component of the given 
        name recursively; all but the last component must exist

मैंने कभी भी उपयोग के मामले का सामना नहीं किया है जहाँ MY_DIRसही गणना नहीं की गई है। यदि आप अपनी स्क्रिप्ट को अपने $PATHकाम में सिम्कलिन के माध्यम से एक्सेस करते हैं ।


अच्छा और सरल समाधान है, और मेरे लिए प्रसिद्ध रूप से स्क्रिप्ट आह्वान के कई रूपों में प्रसिद्ध है जो मैं सोच सकता था। धन्यवाद।
ब्रायन क्लाइन

गायब उद्धरण के साथ मुद्दों के अलावा, क्या कोई वास्तविक उपयोग का मामला है जहां आप $0सीधे उपयोग के बजाय प्रतीकात्मक लिंक को हल करना चाहते हैं?
l0b0

1
@ l0b0: अपनी स्क्रिप्ट की कल्पना करें कि /home/you/script.shआप cd /homeअपनी स्क्रिप्ट वहां से चला सकते हैं क्योंकि ./you/script.shइस मामले dirname $0में वापस आ जाएगी ./youऔर अन्य स्क्रिप्ट सहित असफल हो जाएगी
dr.scre

1
महान सुझाव, हालाँकि, मुझे इसके लिए अपने चर को पढ़ने के लिए निम्नलिखित करने की आवश्यकता थी MY_DIR=$(dirname $(readlink -f $0)); source $MY_DIR/incl.sh
er फ्रेडरिक ओलिन्जर

21

इस सवाल के जवाब का एक संयोजन सबसे मजबूत समाधान प्रदान करता है।

यह निर्भरता और निर्देशिका संरचना के महान समर्थन के साथ उत्पादन-ग्रेड स्क्रिप्ट में हमारे लिए काम करता है:

#! / Bin / bash

# वर्तमान स्क्रिप्ट का पूर्ण पथ
यह = `रीडलिंक -f" $ {BASH_SOURCE [0]} "2> / देव / अशक्त || गूंज $ 0`

# वह निर्देशिका जहाँ वर्तमान स्क्रिप्ट रहती है
DIR = `dirname" $ ​​{THIS} ""

# 'डॉट' का अर्थ है 'स्रोत', यानी 'शामिल':
। "$ DIR / compile.sh"

विधि इन सभी का समर्थन करती है:

  • पथ में रिक्त स्थान
  • लिंक (के माध्यम से readlink)
  • ${BASH_SOURCE[0]} से ज्यादा मजबूत है $0

1
यह = readlink -f "${BASH_SOURCE[0]}" 2>/dev/null||echo $0 यदि आपका रीडिंक व्यस्त है v1Box
रोश

@AlexxRoche धन्यवाद! क्या यह सभी लिनक्स पर काम करेगा?
ब्रायन हाक

1
मैं ऐसी उम्मीद करूंगा। डेबियन सिड पर काम करने के लिए लगता है 3.16 और QNAP के armv5tel 3.4.6 लिनक्स।
एलेक्स

2
मैंने इसे इस एक पंक्ति में रखा:DIR=$(dirname $(readlink -f "${BASH_SOURCE[0]}" 2>/dev/null||echo $0)) # https://stackoverflow.com/a/34208365/
एक्यूमेनस

20
SRC=$(cd $(dirname "$0"); pwd)
source "${SRC}/incl.sh"

1
मुझे संदेह है कि आपने "cd ..." के लिए मतदान किया जब dirname "$ 0" को एक ही बात पूरी करनी चाहिए ...
हारून एच।

7
वर्तमान निर्देशिका से स्क्रिप्ट निष्पादित होने पर भी यह कोड निरपेक्ष पथ पर वापस आ जाएगा। $ (dirname "$ 0") अकेले ही वापस आएगा "।"
अधिकतम

1
और + ./incl.shके समान मार्ग का समाधान करता है । तो डायरेक्टरी बदलने से क्या फायदा? cdpwd
l0b0

कभी-कभी आपको स्क्रिप्ट के पूर्ण पथ की आवश्यकता होती है, उदाहरण के लिए जब आपको निर्देशिकाओं को आगे और पीछे बदलना होता है।
लैरीक्स डेसीडुआ

15

यह स्क्रिप्ट के सॉरी होने पर भी काम करता है:

source "$( dirname "${BASH_SOURCE[0]}" )/incl.sh"

क्या आप बता सकते हैं कि "[0]" का उद्देश्य क्या है?
रे

1
@ रा BASH_SOURCEरास्ते का एक सरणी है, जो कॉल-स्टैक के अनुरूप है। पहला तत्व स्टैक में सबसे हालिया स्क्रिप्ट से मेल खाता है, जो वर्तमान में निष्पादित स्क्रिप्ट है। दरअसल, $BASH_SOURCEएक चर के रूप में कहा जाता है डिफ़ॉल्ट रूप से अपने पहले तत्व तक फैलता है, इसलिए [0]यहां आवश्यक नहीं है। देखें इस लिंक जानकारी के लिए।
जोनाथन एच

10

1. सबसे छोटा

मैंने लगभग हर सुझाव की खोज की और यहाँ मेरे लिए सबसे साफ काम है:

script_root=$(dirname $(readlink -f $0))

यह तब भी काम करता है जब स्क्रिप्ट को एक $PATHनिर्देशिका में सम्‍मिलित किया जाता है ।

इसे यहां देखें: https://github.com/pendashteh/hcagent/blob/master/bin/cagent

2. सबसे अच्छे

# Copyright https://stackoverflow.com/a/13222994/257479
script_root=$(ls -l /proc/$$/fd | grep "255 ->" | sed -e 's/^.\+-> //')

यह वास्तव में इस पृष्ठ पर एक और उत्तर से है, लेकिन मैं इसे अपने उत्तर में भी जोड़ रहा हूं!

2. सबसे विश्वसनीय

वैकल्पिक रूप से, दुर्लभ मामलों में जो काम नहीं करते थे, यहां बुलेट प्रूफ दृष्टिकोण है:

# Copyright http://stackoverflow.com/a/7400673/257479
myreadlink() { [ ! -h "$1" ] && echo "$1" || (local link="$(expr "$(command ls -ld -- "$1")" : '.*-> \(.*\)$')"; cd $(dirname $1); myreadlink "$link" | sed "s|^\([^/].*\)\$|$(dirname $1)/\1|"); }
whereis() { echo $1 | sed "s|^\([^/].*/.*\)|$(pwd)/\1|;s|^\([^/]*\)$|$(which -- $1)|;s|^$|$1|"; } 
whereis_realpath() { local SCRIPT_PATH=$(whereis $1); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)\$|$(dirname ${SCRIPT_PATH})/\1|"; } 

script_root=$(dirname $(whereis_realpath "$0"))

आप इसे taskrunnerस्रोत में कार्रवाई में देख सकते हैं : https://github.com/pendashteh/taskrunner/blob/master/bin/taskrunner

उम्मीद है कि इस मदद से किसी को वहाँ :)

इसके अलावा, कृपया इसे एक टिप्पणी के रूप में छोड़ दें यदि कोई आपके लिए काम नहीं करता है और आपके ऑपरेटिंग सिस्टम और एमुलेटर का उल्लेख करता है। धन्यवाद!


7

आपको अन्य लिपियों के स्थान को निर्दिष्ट करने की आवश्यकता है, इसके आसपास कोई अन्य तरीका नहीं है। मैं आपकी स्क्रिप्ट के शीर्ष पर एक विन्यास योग्य चर सुझाएगा:

#!/bin/bash
installpath=/where/your/scripts/are

. $installpath/incl.sh

echo "The main script"

वैकल्पिक रूप से, आप जोर देकर कह सकते हैं कि उपयोगकर्ता एक पर्यावरण चर बनाए रखता है जो यह दर्शाता है कि आपका कार्यक्रम घर पर कहाँ है, जैसे कि PROG_HOME या किसी भी प्रकार का। यह स्वचालित रूप से /etc/profile.d/ में उस जानकारी के साथ एक स्क्रिप्ट बनाकर उपयोगकर्ता के लिए आपूर्ति की जा सकती है, जो उपयोगकर्ता द्वारा लॉग इन करने पर हर बार खट्टा हो जाएगा।


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

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

6

मेरा सुझाव है कि आप एक सेटनव स्क्रिप्ट बनाएं जिसका एकमात्र उद्देश्य आपके सिस्टम में विभिन्न घटकों के लिए स्थान प्रदान करना है।

अन्य सभी स्क्रिप्ट्स तब इस स्क्रिप्ट को स्रोत बनाएंगे ताकि सेटेन स्क्रिप्ट का उपयोग करके सभी स्क्रिप्ट्स पर सभी स्थान सामान्य हों।

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

हमने अपने बिल्ड बंदर पर ऐसी तकनीक का इस्तेमाल किया जो लगभग 2,000 kSLOC की परियोजना में निरंतर एकीकरण के लिए उपयोग किया गया था।


3

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

तब सभी स्क्रिप्ट्स का स्रोत उस स्क्रिप्ट को बदलना चाहिए और परिवर्तन को स्थापित करना चाहिए, आपको केवल इसे एक स्थान पर बदलना होगा। चीजों को और अधिक बनाता है, एर, Futureproof। भगवान मैं उस शब्द से नफरत है! (-:

BTW आपको अपने उदाहरण में दिखाए गए तरीके से $ {installpath} का उपयोग करते हुए वास्तव में चर का उल्लेख करना चाहिए:

. ${installpath}/incl.sh

यदि ब्रेसिज़ को छोड़ दिया जाता है, तो कुछ गोले चर "इनस्टैपथ / incl.sh" का प्रयास करेंगे और विस्तारित करेंगे!


3

शेल स्क्रिप्ट लोडर इसके लिए मेरा समाधान है।

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

यह बैश के लिए काम करता है उनमें से हर एक के लिए अनुकूलित स्क्रिप्ट के साथ , ksh , पीडी ksh और zsh के है; और अन्य शेल जो मूल रूप से ऐश , डैश , हिरलूम श आदि जैसे मूल श के साथ संगत हैं , एक सार्वभौमिक लिपि के माध्यम से जो शेल प्रदान कर सकने वाली सुविधाओं के आधार पर अपने कार्यों को स्वचालित रूप से अनुकूलित करता है।

[फाउर्डेड उदाहरण]

start.sh

यह एक वैकल्पिक स्टार्टर स्क्रिप्ट है। यहां स्टार्टअप विधियों को रखना केवल एक सुविधा है और इसके बजाय मुख्य स्क्रिप्ट में रखा जा सकता है। यदि स्क्रिप्ट को संकलित किया जाना है तो इस स्क्रिप्ट की भी आवश्यकता नहीं है।

#!/bin/sh

# load loader.sh
. loader.sh

# include directories to search path
loader_addpath /usr/lib/sh deps source

# load main script
load main.sh

main.sh

include a.sh
include b.sh

echo '---- main.sh ----'

# remove loader from shellspace since
# we no longer need it
loader_finish

# main procedures go from here

# ...

a.sh

include main.sh
include a.sh
include b.sh

echo '---- a.sh ----'

b.sh

include main.sh
include a.sh
include b.sh

echo '---- b.sh ----'

उत्पादन:

---- b.sh ----
---- a.sh ----
---- main.sh ----

जो सबसे अच्छी स्क्रिप्ट है, उस पर आधारित स्क्रिप्ट भी उपलब्ध कंपाइलर के साथ एकल स्क्रिप्ट बनाने के लिए संकलित की जा सकती है।

यहां एक परियोजना है जो इसका उपयोग करती है: http://sourceforge.net/p/playshell/code/ci/master/tree/ । यह स्क्रिप्ट को संकलित किए बिना या उसके बिना पोर्ट्रेट रूप से चल सकता है। एकल स्क्रिप्ट का निर्माण करने के लिए संकलन भी हो सकता है, और स्थापना के दौरान सहायक होता है।

मैंने किसी भी रूढ़िवादी पार्टी के लिए एक सरल प्रोटोटाइप भी बनाया है जो इस बात का एक संक्षिप्त विचार रखना चाहता है कि कार्यान्वयन स्क्रिप्ट कैसे काम करती है: https://sourceforge.net/p/loader/code/ci/base/tree/loader-include-prototype .बश । यह छोटा है और कोई भी अपने मुख्य स्क्रिप्ट में कोड को शामिल कर सकता है यदि वे चाहते हैं कि उनका कोड बश 4.0 या नए के साथ चलाने का इरादा है, और यह भी उपयोग नहीं करता है eval


3
evalनिर्भरता को लोड करने के लिए एड कोड की 100 से अधिक लाइनों वाले बैश स्क्रिप्ट के 12 किलोबाइट । आउच
l0b0

1
evalहमेशा नीचे के पास तीन ब्लॉकों में से एक हमेशा चलाया जाता है। इसलिए इसकी आवश्यकता है या नहीं, यह सुनिश्चित है कि इसका उपयोग किया जा रहा है eval
l0b0

3
यह स्पष्ट कॉल सुरक्षित है और इसका उपयोग यदि आपके पास बैश 4.0+ है तो इसका उपयोग नहीं किया जाता है। मैं देखता हूं, आप उन पुराने समय के स्क्रिप्टर्स में से एक हैं जो सोचते हैं कि evalयह शुद्ध बुराई है, और इसके बजाय इसका अच्छा उपयोग करना नहीं जानते।
konsolebox

1
मुझे नहीं पता कि आपके "इस्तेमाल नहीं" से क्या मतलब है, लेकिन यह चलाया जाता है। और कुछ वर्षों के बाद मेरी नौकरी के हिस्से के रूप में स्क्रिप्टिंग के बाद, हाँ, मैं पहले से कहीं ज्यादा आश्वस्त हूं कि evalयह बुराई है।
l0b0

1
फ़ाइलों को फ़्लैग करने के दो पोर्टेबल, सरल तरीके तुरंत दिमाग में आते हैं: या तो उनके इनकोड नंबर द्वारा, या एक फाइल में एनयूएल-पृथक पथ डालकर।
l0b0

2

व्यक्तिगत रूप से सभी पुस्तकालयों को एक libफ़ोल्डर में रखें और importउन्हें लोड करने के लिए फ़ंक्शन का उपयोग करें।

फ़ोल्डर संरचना

यहां छवि विवरण दर्ज करें

script.sh अंतर्वस्तु

# Imports '.sh' files from 'lib' directory
function import()
{
  local file="./lib/$1.sh"
  local error="\e[31mError: \e[0mCannot find \e[1m$1\e[0m library at: \e[2m$file\e[0m"
  if [ -f "$file" ]; then
     source "$file"
    if [ -z $IMPORTED ]; then
      echo -e $error
      exit 1
    fi
  else
    echo -e $error
    exit 1
  fi
}

ध्यान दें कि यह आयात फ़ंक्शन आपकी स्क्रिप्ट की शुरुआत में होना चाहिए और फिर आप इस तरह से अपने पुस्तकालयों को आसानी से आयात कर सकते हैं:

import "utils"
import "requirements"

प्रत्येक लायब्रेरी के शीर्ष पर एक एकल पंक्ति जोड़ें (यानी utils.sh):

IMPORTED="$BASH_SOURCE"

अब आप अंदर कार्यों के लिए उपयोग किया utils.shऔर requirements.shसेscript.sh

TODO: एक एकल shफ़ाइल बनाने के लिए एक लिंकर लिखें


क्या यह उस स्क्रिप्ट के बाहर निष्पादित करने की समस्या को भी हल करता है जिसमें वह है?
आरोन एच।

@AaronH। यह बड़ी परियोजनाओं में निर्भरता को शामिल करने के लिए एक संरचित तरीका है।
Xaqron

1

स्रोत या $ 0 का उपयोग करने से आपको अपनी स्क्रिप्ट का वास्तविक मार्ग नहीं मिलेगा। आप इसके वास्तविक पथ को पुनः प्राप्त करने के लिए स्क्रिप्ट की प्रक्रिया आईडी का उपयोग कर सकते हैं

ls -l       /proc/$$/fd           | 
grep        "255 ->"            |
sed -e      's/^.\+-> //'

मैं इस स्क्रिप्ट का उपयोग कर रहा हूं और इसने हमेशा मेरी अच्छी सेवा की है :)


1

मैंने अपनी सभी स्टार्टअप स्क्रिप्ट्स को एक .bashrc.d डायरेक्टरी में रखा। यह ऐसी जगहों पर एक सामान्य तकनीक है जैसे /etc/profile.d आदि।

while read file; do source "${file}"; done <<HERE
$(find ${HOME}/.bashrc.d -type f)
HERE

ग्लोबिंग का उपयोग कर समाधान के साथ समस्या ...

for file in ${HOME}/.bashrc.d/*.sh; do source ${file};done

... क्या आपके पास एक फ़ाइल सूची हो सकती है जो "बहुत लंबी" है। जैसे एक दृष्टिकोण ...

find ${HOME}/.bashrc.d -type f | while read file; do source ${file}; done

... चलाता है, लेकिन पर्यावरण को इच्छानुसार नहीं बदलता है।


1

बेशक, प्रत्येक अपने स्वयं के, लेकिन मुझे लगता है कि नीचे ब्लॉक बहुत ठोस है। मेरा मानना ​​है कि इसमें निर्देशिका खोजने के लिए "सबसे अच्छा" तरीका शामिल है, और दूसरे बैश स्क्रिप्ट को कॉल करने का "सबसे अच्छा" तरीका है:

scriptdir=`dirname "$BASH_SOURCE"`
source $scriptdir/incl.sh

echo "The main script"

तो यह अन्य लिपियों को शामिल करने का "सबसे अच्छा" तरीका हो सकता है। यह एक और "सर्वश्रेष्ठ" उत्तर पर आधारित है जो एक बैश स्क्रिप्ट को बताता है जहां इसे संग्रहीत किया जाता है


1

यह मज़बूती से काम करना चाहिए:

source_relative() {
 local dir="${BASH_SOURCE%/*}"
 [[ -z "$dir" ]] && dir="$PWD"
 source "$dir/$1"
}

source_relative incl.sh

0

हमें केवल उस फ़ोल्डर का पता लगाना है जहां हमारा incl.sh और main.sh संग्रहीत है; बस इसके साथ अपने main.sh को बदलें:

main.sh

#!/bin/bash

SCRIPT_NAME=$(basename $0)
SCRIPT_DIR="$(echo $0| sed "s/$SCRIPT_NAME//g")"
source $SCRIPT_DIR/incl.sh

echo "The main script"

गलत के हवाले से, के अनावश्यक उपयोग echo, और के गलत उपयोग sedके gविकल्प। -1।
l0b0

वैसे भी, इस स्क्रिप्ट को काम करने के लिए: SCRIPT_DIR=$(echo "$0" | sed "s/${SCRIPT_NAME}//")और फिरsource "${SCRIPT_DIR}incl.sh"
Krzysiek

0

man hierस्क्रिप्ट के लिए उपयुक्त जगह के अनुसार शामिल है/usr/local/lib/

/ Usr / स्थानीय / lib

स्थानीय रूप से स्थापित प्रोग्राम्स से जुड़ी फाइलें।

व्यक्तिगत रूप से मैं /usr/local/lib/bash/includesशामिल करना पसंद करता हूं । इस तरह से लिबास को शामिल करने के लिए bash-helper lib है:

#!/bin/bash

. /usr/local/lib/bash/includes/bash-helpers.sh

include api-client || exit 1                   # include shared functions
include mysql-status/query-builder || exit 1   # include script functions

# include script functions with status message
include mysql-status/process-checker; status 'process-checker' $? || exit 1
include mysql-status/nonexists; status 'nonexists' $? || exit 1

बैश-हेल्पर्स में स्टेटस आउटपुट शामिल है


-5

आप भी उपयोग कर सकते हैं:

PWD=$(pwd)
source "$PWD/inc.sh"

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