অন্যান্য স্ক্রিপ্টগুলি কীভাবে অন্তর্ভুক্ত করা যায়?


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

... এখন, আপনি যদি অন্য কোনও জায়গা থেকে শেল স্ক্রিপ্টটি চালানোর চেষ্টা করেন তবে এটি আপনার পথে না থাকলে এটি অন্তর্ভুক্ত খুঁজে পাবে না।

আপনার স্ক্রিপ্টটি অন্তর্ভুক্ত স্ক্রিপ্টটি খুঁজে পেতে পারে তা নিশ্চিত করার একটি ভাল উপায় কী, বিশেষত উদাহরণস্বরূপ, স্ক্রিপ্টটি বহনযোগ্য হতে হবে?



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
@ ফিলিপ, এই প্রবেশের লেখক সঠিক, এটি জটিল, এবং সেখানে গ্যাটাচস রয়েছে। তবে এটি কিছু মূল বিষয় অনুপস্থিত, প্রথমত, লেখক আপনার বাশ স্ক্রিপ্টটি দিয়ে আপনি যা করতে যাচ্ছেন সে সম্পর্কে পুরোপুরি অনেক কিছু ধরে নিয়েছে। পাইথন স্ক্রিপ্ট এর নির্ভরতা ছাড়া চালিত হবে বলে আমি আশা করবো না। বাশ একটি আঠালো ভাষা যা আপনাকে এমন কাজগুলি দ্রুত করতে দেয় যা অন্যথায় কঠিন হতে পারে। আপনার যখন আপনার বিল্ড সিস্টেমটি কাজ করার দরকার হয় তখন ব্যবহারবাদ (এবং স্ক্রিপ্ট নির্ভরতা খুঁজে পেতে সক্ষম না হওয়ার বিষয়ে একটি দুর্দান্ত সতর্কতা) জয়ী হয়।
অ্যারন এইচ।

11
সবেমাত্র BASH_SOURCEঅ্যারে সম্পর্কে শিখেছি এবং কীভাবে এই অ্যারেতে প্রথম উপাদানটি সর্বদা বর্তমান উত্সকে নির্দেশ করে।
হরিদসভ

6
স্ক্রিপ্টগুলি পৃথক স্থানে থাকলে এটি কাজ করবে না। উদাহরণস্বরূপ /home/me/main.sh কলগুলি / home/me/test/inc.sh ডায়ারনেম হিসাবে / হোম / আমাকে ফিরে আসবে। sacii উত্তর BASH_SOURCE ব্যবহার করে একটি ভাল সমাধান পাওয়া যাবে stackoverflow.com/a/12694189/1000011
opticyclic

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
@ স্যাসিআই আমি জানতে পারি কখন লাইনটি if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fiদরকার? কমান্ডগুলি চালানোর জন্য কোনও বাশ প্রম্পটে আটকানো হচ্ছে তবে আমি এটির জন্য একটি প্রয়োজনীয়তা পেতে পারি। যাইহোক, যদি কোনও স্ক্রিপ্ট ফাইলের প্রসঙ্গে চলে তবে আমি এর প্রয়োজন দেখতে পাচ্ছি না ...
জনি ওয়াং

2
এটি লক্ষণীয় যে এটি একাধিক sourceগুলি জুড়ে প্রত্যাশার মতো কাজ করে (মানে আপনি যদি অন্য কোনও ডিরেক্টরিতে অন্য কোনও sourceস্ক্রিপ্ট করেন sourceএবং এটি এখনও কাজ করে)।
সিরো কোস্টার

4
${BASH_SOURCE[0]}আপনি কি সর্বশেষতম কল চান এটির মতো হওয়া উচিত নয় ? এছাড়াও, ব্যবহারের DIR=$(dirname ${BASH_SOURCE[0]})ফলে আপনি যদি এই শর্তটি থেকে মুক্তি পেতে পারেন
kshenoy

1
আপনি কি এই স্নিপেটটি সিসি0 এর মতো কোনও অ্যাট্রিবিউট প্রয়োজনীয় লাইসেন্সের অধীনে উপলব্ধ করতে বা এটি সর্বজনীন ডোমেনে প্রকাশ করতে ইচ্ছুক? আমি এই ভারব্যাটিমটি ব্যবহার করতে চাই তবে প্রতিটি একক স্ক্রিপ্টের শীর্ষে এট্রিবিউটটি স্থাপন করা বিরক্তিকর!
BeeOnRope

52

এর বিকল্প:

scriptPath=$(dirname $0)

হল:

scriptPath=${0%/*}

.. ডায়ারনেমের উপর নির্ভরতা না থাকার সুবিধা, যা অন্তর্নির্মিত কমান্ড নয় (এবং সর্বদা এমুলেটরগুলিতে উপলব্ধ থাকে না)


2
basePath=$(dirname $0)যখন স্ক্রিপ্টযুক্ত ফাইলটি উত্সাহিত হয় তখন আমাকে ফাঁকা মান দিয়েছিল।
প্রেয়াগআপড

41

যদি এটি একই ডিরেক্টরিতে থাকে তবে আপনি ব্যবহার করতে পারেন dirname $0:

#!/bin/bash

source $(dirname $0)/incl.sh

echo "The main script"

2
দুটি ক্ষতি: 1) $0হ'ল ./t.shএবং ডায়ারনেম রিটার্ন .; 2) cd binফেরার পরে .সঠিক নয়। $BASH_SOURCEএর চেয়ে ভাল আর কিছু নয়।
18446744073709551615

আরেকটি ক্ষতি: ডিরেক্টরি নামের ফাঁকা জায়গা দিয়ে এটি ব্যবহার করে দেখুন।
হুবার্ট গ্রেজস্কোইয়াক

source "$(dirname $0)/incl.sh"এই ক্ষেত্রেগুলির জন্য কাজ করে
dsm

27

আমি মনে করি এটির সর্বোত্তম উপায় হ'ল ক্রিস বোরানের উপায়টি ব্যবহার করা, তবে আপনার এমআইওয়াইডিআরকে এইভাবে গণনা করা উচিত:

#!/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
ফ্রেডেরিক ওলিঞ্জার

21

এই প্রশ্নের উত্তরের সংমিশ্রণটি সবচেয়ে শক্তিশালী সমাধান সরবরাহ করে।

এটি নির্ভরতা এবং ডিরেক্টরি কাঠামোর দুর্দান্ত সমর্থন সহ উত্পাদন-গ্রেড স্ক্রিপ্টগুলিতে আমাদের জন্য কাজ করেছে:

#! / বিন / ব্যাশ

# বর্তমান স্ক্রিপ্টের সম্পূর্ণ পথ
এই = `রিডলিঙ্ক -f" $ AS বাস_সেসার্স [0]} "2> / দেব / নাল || প্রতিধ্বনি $ 0`

# বর্তমান স্ক্রিপ্টটি যে ডিরেক্টরিটি থাকে
DIR = ir dirname "$ {এটি}" ``

# 'ডট' অর্থ 'উত্স', অর্থাৎ 'অন্তর্ভুক্ত':
। "$ Dir / compile.sh"

পদ্ধতি এই সমস্ত সমর্থন করে:

  • পথে ফাঁকা জায়গা
  • লিঙ্কগুলি (এর মাধ্যমে readlink)
  • ${BASH_SOURCE[0]} এর চেয়ে বেশি শক্তিশালী $0

1
এই = readlink -f "${BASH_SOURCE[0]}" 2>/dev/null||echo $0 যদি আপনার পঠন লিঙ্কটি ব্যাসিবক্স v1.01 হয়
রোচে

@ অ্যালেক্সএক্সরোচ আপনাকে ধন্যবাদ! এটি কি সমস্ত লিনাক্সে কাজ করবে?
ব্রায়ান হক

1
আমি তাই আশা করি। দেবিয়ান সিড 3.16 এবং কিউএনএপি এর আর্মভি 5tel 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
আমার সন্দেহ হয় যে আপনি "সিডি ..." এর পক্ষে ভোট পেয়েছিলেন যখন ডায়ারনেম "name 0" একই কাজটি সম্পাদন করা উচিত ...
অ্যারন এইচ।

7
বর্তমান ডিরেক্টরি থেকে স্ক্রিপ্ট কার্যকর করা হলেও এই কোডটি পরম পাথ ফিরে আসবে। alone (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/hcagent

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"

বিকল্পভাবে, আপনি জোর দিয়ে বলতে পারেন যে ব্যবহারকারীরা একটি পরিবেশের পরিবর্তনশীল বজায় রাখবেন যা আপনার প্রোগ্রাম হোমটি কোথায় রয়েছে তা প্রোগোহোম বা সামসুচের মতো। এটি /etc/profile.d/ এ সেই তথ্য সহ একটি স্ক্রিপ্ট তৈরি করে ব্যবহারকারীর জন্য স্বয়ংক্রিয়ভাবে সরবরাহ করা যেতে পারে, যা ব্যবহারকারী যখনই লগ ইন করে ততক্ষণে উত্সাহিত হবে।


1
আমি সুনির্দিষ্টতার জন্য আকাঙ্ক্ষার প্রশংসা করি, তবে অন্তর্ভুক্ত স্ক্রিপ্টগুলি অন্য প্যাকেজের অংশ না হলে কেন পুরো পাথের প্রয়োজন হবে তা আমি দেখতে পাচ্ছি না। সুনির্দিষ্ট পার্থক্যটি আমি কোনও নির্দিষ্ট আপেক্ষিক পথ থেকে লোড করে দেখছি না (যেমন একই দির যেখানে স্ক্রিপ্টটি চালাচ্ছে vs) একটি নির্দিষ্ট পূর্ণপথ বনাম। কেন আপনি বলেন যে এর আশেপাশে কোনও উপায় নেই?
অ্যারন এইচ।

4
কারণ আপনার স্ক্রিপ্টটি যে ডিরেক্টরিটি চালাচ্ছে সেই ডিরেক্টরিটি যেখানে আপনার স্ক্রিপ্টে অন্তর্ভুক্ত করতে চান সেই স্ক্রিপ্টগুলি অবস্থিত নয়। আপনি যে স্ক্রিপ্টগুলি ইনস্টল করেছেন সেগুলি লোড করতে চান এবং এটি রান-টাইমে কোথায় রয়েছে তা বলার কোনও নির্ভরযোগ্য উপায় নেই। একটি নির্দিষ্ট অবস্থান ব্যবহার না করাও ভুল (অর্থাত্ হ্যাকার সরবরাহিত) স্ক্রিপ্ট অন্তর্ভুক্ত করার জন্য এবং এটি চালানোর জন্য একটি ভাল উপায়।
স্টিভ বেকার

6

আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি এমন একটি সেলেনভ স্ক্রিপ্ট তৈরি করুন যার একমাত্র উদ্দেশ্য আপনার সিস্টেমের বিভিন্ন অংশের জন্য অবস্থান সরবরাহ করা।

অন্যান্য সমস্ত স্ক্রিপ্টগুলি তখন এই স্ক্রিপ্টটির উত্স তৈরি করবে যাতে সেটেনভ স্ক্রিপ্ট ব্যবহার করে সমস্ত অবস্থানগুলি সমস্ত স্ক্রিপ্টগুলিতে সাধারণ হয়।

ক্রোনজবস চালানোর সময় এটি খুব দরকারী। ক্রোন চলাকালীন আপনি একটি ন্যূনতম পরিবেশ পাবেন তবে আপনি যদি সমস্ত ক্রোন স্ক্রিপ্টগুলিতে প্রথমে সেটেনভ স্ক্রিপ্ট অন্তর্ভুক্ত করেন তবে আপনি যে পরিবেশটি ক্রোনজগুলি চালিত করতে চান তা নিয়ন্ত্রণ করতে এবং সিঙ্ক্রোনাইজ করতে সক্ষম হবেন।

আমরা আমাদের বিল্ড বানরটিতে এমন একটি প্রযুক্তি ব্যবহার করেছি যা প্রায় ২ হাজার কেএসএলসিপি প্রকল্পের ক্রমাগত সংহতকরণের জন্য ব্যবহৃত হয়েছিল।


3

স্টিভের জবাবটি অবশ্যই সঠিক কৌশল তবে এটি পুনরুদ্ধার করা উচিত যাতে আপনার ইনস্টলপথ পরিবর্তনশীলটি একটি পৃথক পরিবেশ স্ক্রিপ্টে থাকে যেখানে এই জাতীয় সমস্ত ঘোষণা করা হয়।

তারপরে সমস্ত স্ক্রিপ্টগুলি সেই স্ক্রিপ্টের উত্স দেয় এবং ইনস্টলপথ পরিবর্তন হওয়া উচিত, আপনাকে কেবল এটি একটি স্থানে পরিবর্তন করতে হবে। জিনিসগুলিকে আরও বেশি করে, ভবিষ্যতের প্রতিরোধী করে তোলে। Godশ্বর আমি এই শব্দটিকে ঘৃণা করি! (-:

বিটিডাব্লু আপনার উদাহরণটিতে প্রদর্শিত ভাবে ব্যবহার করার সময় আপনার সত্যিকারের ath {ইনস্টলপথ the ব্যবহার করে চলকটি উল্লেখ করা উচিত:

. ${installpath}/incl.sh

যদি ধনুর্বন্ধনীগুলি ছেড়ে যায়, কিছু শেলগুলি "ইনস্টলপথ / Incl.sh" চলকটি চেষ্টা করে প্রসারিত করবে!


3

শেল স্ক্রিপ্ট লোডার এটির জন্য আমার সমাধান।

এটি অন্তর্ভুক্ত () নামের একটি ফাংশন সরবরাহ করে যা একটি স্ক্রিপ্ট উল্লেখ করার জন্য অনেক স্ক্রিপ্টে বহুবার কল করা যেতে পারে তবে কেবল একবার স্ক্রিপ্টটি লোড করবে। ফাংশনটি সম্পূর্ণ পাথ বা আংশিক পাথ গ্রহণ করতে পারে (স্ক্রিপ্ট কোনও অনুসন্ধানের পথে সন্ধান করা হয়)। লোড () নামে একটি অনুরূপ ফাংশনও সরবরাহ করা হয়েছে যা স্ক্রিপ্টগুলি নিঃশর্ত লোড করবে।

এটি bash , ksh , pd ksh এবং zsh এর জন্য প্রতিটিগুলির জন্য অনুকূলিত স্ক্রিপ্টগুলির সাথে কাজ করে; এবং অন্যান্য শেলগুলি যে সর্বজনীন স্ক্রিপ্টের মাধ্যমে মূল শের মতো ছাই , ড্যাশ , উত্তরাধিকারী শ , ইত্যাদি ইত্যাদির সাথে সাধারণভাবে সুসংগত হয় যা শেল সরবরাহ করতে পারে তার বৈশিষ্ট্যগুলির উপর নির্ভর করে স্বয়ংক্রিয়ভাবে তার ক্রিয়াকে অনুকূল করে দেয়।

[প্রিয় উদাহরণ]

start.sh

এটি একটি alচ্ছিক স্টার্টার স্ক্রিপ্ট। এখানে স্টার্টআপ পদ্ধতিগুলি স্থাপন করা কেবল একটি সুবিধা এবং পরিবর্তে মূল স্ক্রিপ্টে রাখা যেতে পারে। স্ক্রিপ্টগুলি সংকলন করতে হলে এই স্ক্রিপ্টটিরও প্রয়োজন নেই।

#!/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-incolve-prototype .বাশ । এটি ছোট এবং যে কেউ তাদের কোডটি বাশ ৪.০ বা আরও নতুন দিয়ে চালানোর উদ্দেশ্যে তৈরি করতে চাইলে তাদের কোডটি কেবল তাদের মূল স্ক্রিপ্টে অন্তর্ভুক্ত করতে পারে এবং এটি ব্যবহারও করে না eval


3
evalনির্ভরতা লোড করতে এ্যাড কোডের 100 টির বেশি লাইনযুক্ত 12 কিলোবাইট বাশ স্ক্রিপ্ট । সেকি
l0b0

1
ঠিক evalনীচের দিকে তিনটি ব্লকের মধ্যে একটি সর্বদা চালিত হয়। সুতরাং এটির প্রয়োজন আছে বা না, এটি অবশ্যই ব্যবহার করছে eval
l0b0

3
এই alভাল কলটি নিরাপদ এবং আপনার কাছে বাশ 4.0+ থাকলে এটি ব্যবহৃত হয় না। আমি দেখতে পেয়েছি, আপনি সেই পুরানো সময়ের স্ক্রিপ্টারের একজন যাঁরা evalখাঁটি মন্দ বলে মনে করেন, এবং পরিবর্তে কীভাবে এটির ভাল ব্যবহার করবেন তা জানেন না।
কনসোলবক্স

1
আপনি "ব্যবহৃত না" বলতে কী বোঝায় তা আমি জানি না, তবে এটি চালানো হয়েছে। এবং আমার কাজের অংশ হিসাবে শেল স্ক্রিপ্টিংয়ের কয়েক বছর পরে, হ্যাঁ, আমি আগের চেয়ে বেশি বিশ্বাস করি যে evalএটি খারাপ that
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"

প্রতিটি লাইব্রেরির শীর্ষে একটি একক লাইন যুক্ত করুন (যেমন ইউটস.শ):

IMPORTED="$BASH_SOURCE"

এখন আপনার ভিতরে utils.shএবং requirements.shথেকে ফাংশনগুলিতে অ্যাক্সেস রয়েছেscript.sh

টোডো: একটি একক shফাইল তৈরি করতে লিঙ্কার লিখুন


এটি কি ডিরের বাইরে স্ক্রিপ্টটি কার্যকর করার সমস্যাটি সমাধান করে?
অ্যারন এইচ।

@AaronH। না এটি বড় প্রকল্পগুলির নির্ভরতা অন্তর্ভুক্ত করার জন্য একটি কাঠামোগত উপায়।
Xaqron

1

উত্স বা $ 0 ব্যবহার করা আপনাকে আপনার স্ক্রিপ্টের আসল পথ দেয় না। আপনি স্ক্রিপ্টটির প্রকৃত পথটি পুনরুদ্ধার করতে প্রক্রিয়া আইডি ব্যবহার করতে পারেন

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

আমি এই স্ক্রিপ্টটি ব্যবহার করছি এবং এটি সর্বদা আমাকে ভালভাবে পরিবেশন করেছে :)


1

আমি আমার সমস্ত প্রারম্ভিক স্ক্রিপ্টগুলি .bashrc.d ডিরেক্টরিতে রেখেছি। এটি /etc/profile.d ইত্যাদির মতো জায়গায় একটি সাধারণ কৌশল is

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

#!/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"
ক্রিজিসিক

0

man hierস্ক্রিপ্ট জন্য উপযুক্ত জায়গা অনুযায়ী/usr/local/lib/

, / Usr / local / lib

স্থানীয়ভাবে ইনস্টল করা প্রোগ্রামগুলির সাথে যুক্ত ফাইল।

ব্যক্তিগতভাবে আমি /usr/local/lib/bash/includesঅন্তর্ভুক্ত জন্য পছন্দ । নেই ব্যাশ-সাহায্যকারী যে ভাবে লিব সহ liberal এর সংক্ষিপ্ত রূপ:

#!/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
আপনি ধরে নেন যে আপনি একই ডিরেক্টরিতে আছেন যেখানে স্ক্রিপ্টগুলি অবস্থিত। আপনি অন্য কোথাও থাকলে এটি কাজ করবে না।
লুক এম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.