別のシェルスクリプトから1つのシェルスクリプトを呼び出す方法


739

2つのシェルスクリプトがa.shありb.shます。

b.shシェルスクリプト内からどのように呼び出すことができますa.shか?


8
特定のことを教えてください:どのOSとどのシェル、または原則としてその問題について話しているだけですか?サンプルコードも役に立ちます。
jsalonen

14
これは実際には特定の質問ではなく、問題を解決するための以前の取り組みを示しているわけでもありません。
クリス14

1
私が抱えてb.shいた1つの問題は、実行権限がないことでした。確認するのも良いかもしれません。
seth10

./代わりに、スクリプト名の前に追加します。例:b.sh、次を使用:./b.sh
Benny

1
誰かがNo such file or directoryエラーを繰り返し続ける場合は、stackoverflow.com
a / 2920431/1356559

回答:


959

これを行うには、いくつかの方法があります。

  1. 他のスクリプトを実行可能に#!/bin/bashして、先頭に行を追加し、$ PATH環境変数へのファイルのパスを追加します。その後、それを通常のコマンドとして呼び出すことができます。

  2. または、source次の.ようなコマンド(エイリアスは)で呼び出しsource /path/to/scriptます。

  3. または、bashコマンドを使用して実行します/bin/bash /path/to/script

1番目と3番目のメソッドは、スクリプトを別のプロセスとして実行するため、他のスクリプトの変数と関数にはアクセスできません。
2番目のメソッドは、最初のスクリプトのプロセスでスクリプトを実行し、変数と関数を他のスクリプトからプルして、呼び出し元のスクリプトから使用できるようにします。

2番目の方法ではexit、2番目のスクリプトで使用している場合、最初のスクリプトも終了します。これは、1番目と3番目の方法では発生しません。


30
覚えておかchmod a+x /path/to/fileないと、実行可能にならないでしょう。./scriptメソッドにのみ適用されます。
Nathan Lilienthal 2013年

3
> DOS2UNIX <スクリプト名> -彼らはDOSで作成し、次にUNIX環境にアップロードされている場合は、UNIXで実行可能ファイルのエンコーディング/変更形式に覚えている
アビシェーク・チャテジー

3
@cecemel最初と3番目の方法、通常のrun-in-background構文を使用して「非同期」にすることできます。
一部のプログラマー、

16
問題sourceexit、呼び出されたスクリプトのステートメントも同様に終了することです...
Ohad Schneider

18
@ user528025はの.エイリアスでsourceはなく、その逆です。sourcebashの拡張機能ですが、.POSIX互換シェルで機能します。
Score_Under

207

これをチェックしてください。

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."

4
これは、script.shが実行中のスクリプトと同じディレクトリにあると想定しています。スクリプトを別の場所で呼び出したい場合は、次のように言うでしょうsh <path to script>/script.sh
モーガンケニオン

32
これも2つのシェルを使用bashshます。場合でもsh実際にはbash、それは同じように動作しません。使用している場合は#!/bin/bash、おそらく使用する必要がありますbash script.sh(または./script.shそのスクリプトのハッシュバンを使用するだけです)。
Martin Tournoij、2016年

1
chmod +x.shファイルに設定しても、アクセス許可の拒否エラーが発生し続けました。助言がありますか?
isaacは

@isaacweathersがchmod 777を試す
Janac Meena

114

これを行うには、いくつかの方法があります。スクリプトを実行するターミナル:

#!/bin/bash
SCRIPT_PATH="/path/to/script.sh"

# Here you execute your script
"$SCRIPT_PATH"

# or
. "$SCRIPT_PATH"

# or
source "$SCRIPT_PATH"

# or
bash "$SCRIPT_PATH"

# or
eval '"$SCRIPT_PATH"'

# or
OUTPUT=$("$SCRIPT_PATH")
echo $OUTPUT

# or
OUTPUT=`"$SCRIPT_PATH"`
echo $OUTPUT

# or
("$SCRIPT_PATH")

# or
(exec "$SCRIPT_PATH")

これはすべて、スペースのあるパスに適しています!!!


41
それらの違いは何ですか?なぜ一つ、なぜ他の?
ロケットスペーサー2017年

。"$ SCRIPT_PATH"が推奨
Harry Mumford-Turner

1
たとえば、sh "$ SCRIPT_PATH"とbash "$ SCRIPT_PATH"は#​​!/ usr / bin / expectスクリプトを実行しませんが、 "$ SCRIPT_PATH"は実行するだけです。
Tahlor

58

私が探していた答え:

( exec "path/to/script" )

前述のように、exec新しいプロセスを作成せずにシェルを置き換えます。ただし、それをサブシェルに置くことはできますが、これは括弧を使用して行われます。

編集:実際に( "path/to/script" )は十分です。


11
これはかなり複雑なようです。なぜそれだけで呼び出さないの/path/to/scriptですか?execここで必要性がまったくわかりませんか?
Martin Tournoij、2016年

あなたはexecINGしていないので、サブシェルも必要ありません。
Karel Vlk 2017年

6
このスクリプトを引数付きでどのように実行しますか?
Bhargav 2017年

サブスクリプトの出力を引き続きキャプチャする場合は、$(source "path / to / script")
cmcginty

このリンクに従う@Bhargav stackoverflow.com/questions/14302389/...
tpbafk

16

依存します。簡単に言うと...現在のコンソールで変数をロードして実行する場合はsource myshellfile.sh、コードで使用できます。例:

!#/bin/bash
set -x
echo "This is an example of run another INTO this session."
source my_lib_of_variables_and_functions.sh
echo "The function internal_function() is defined into my lib."
returned_value=internal_function()
echo $this_is_an_internal_variable

set +x

ファイルを実行したいだけで、結果が気になる場合は、次のようにできます。

!#/bin/bash
set -x
./executing_only.sh
sh i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x

お役に立てば幸いです。ありがとう。


2
sourcebashの固有の機能です。標準のbourneシェルには.(たとえば. other_script.sh)しかありません。
Martin Tournoij、2016年

15

を使用/bin/shして、(実際のスクリプトを介して)別のスクリプトを呼び出したり実行したりできます。

 # cat showdate.sh
 #!/bin/bash
 echo "Date is: `date`"

 # cat mainscript.sh
 #!/bin/bash
 echo "You are login as: `whoami`"
 echo "`/bin/sh ./showdate.sh`" # exact path for the script file

出力は次のようになります。

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013

1
確かに、これはshowdate.sh/ bin / bashではなく/ bin / shで実行されますか?
クリスワッツ

/bin/sh ./showdate.sh」、「/bin/bash ./showdate.sh」、「./showdate.sh」で試して、ファイルmainscript.shを実行し、同じ出力を得ました。
Ranjithkumar T 2017

10

スクリプトを実行するために、ターミナルに入力した内容を行に追加するだけです!
例えば:

#!bin/bash
./myscript.sh &

実行するスクリプトが同じディレクトリにない場合は、スクリプトの完全なパスを使用してください。
例: `/ home / user / script-directory /./ myscript.sh&


@Carpetsmoker &for background task
Andrei Krasutski

9

最初に、呼び出すファイルを含める必要があります。

#!/bin/bash
. includes/included_file.sh

次に、次のように関数を呼び出します。

#!/bin/bash
my_called_function


9

同じディレクトリに別のファイルがある場合は、次のいずれかを実行できます。

bash another_script.sh

または

source another_script.sh

または

. another_script.sh

bash代わりにを使用するとsource、スクリプトは親スクリプトの環境を変更できません。.一方、コマンドは、POSIX標準であるsourceコマンドは、より読みやすいのbash同義語である.(私が好むsourceオーバー.)。スクリプトが他の場所にある場合は、そのスクリプトへのパスを指定してください。相対パスと完全パスの両方が機能するはずです。


5

一番上の答えは、#!/bin/bash呼び出されているサブスクリプトの最初の行に行を追加することを提案しています。しかし、あなたはシェバングを追加した場合でも、それははるかに高速です*サブシェルでスクリプトを実行し、出力をキャプチャします:

$(source SCRIPT_NAME)

これは、同じインタープリター(たとえば、bashから別のbashスクリプト)を実行し続けたい場合に機能し、サブスクリプトのシバン行が実行されないようにします。

例えば:

#!/bin/bash
SUB_SCRIPT=$(mktemp)
echo "#!/bin/bash" > $SUB_SCRIPT
echo 'echo $1' >> $SUB_SCRIPT
chmod +x $SUB_SCRIPT
if [[ $1 == "--source" ]]; then
  for X in $(seq 100); do
    MODE=$(source $SUB_SCRIPT "source on")
  done
else
  for X in $(seq 100); do
    MODE=$($SUB_SCRIPT "source off")
  done
fi
echo $MODE
rm $SUB_SCRIPT

出力:

~ ❯❯❯ time ./test.sh
source off
./test.sh  0.15s user 0.16s system 87% cpu 0.360 total

~ ❯❯❯ time ./test.sh --source
source on
./test.sh --source  0.05s user 0.06s system 95% cpu 0.114 total

*たとえば、ウイルスまたはセキュリティツールがデバイスで実行されている場合、新しいプロセスを実行するためにさらに100ミリ秒かかる場合があります。



4
 #!/bin/bash

 # Here you define the absolute path of your script

 scriptPath="/home/user/pathScript/"

 # Name of your script

 scriptName="myscript.sh"

 # Here you execute your script

 $scriptPath/$scriptName

 # Result of script execution

 result=$?

1
スペースのあるフォルダscriptPathまたはファイル名の場合は正しくありませんscriptName
Andrei Krasutski

3

新しいファイルが「/ home / satya / app / app_specific_env」であり、ファイルの内容が次のとおりであるとします。

#!bin/bash

export FAV_NUMBER="2211"

このファイル参照を〜/ .bashrcファイルに追加します

source /home/satya/app/app_specific_env

マシンを再起動または再ログインするときはいつでもecho $FAV_NUMBER、ターミナルで試してください。値を出力します。

source ~/.bashrcコマンドラインですぐに効果を確認したい場合に備えて。


3
chmod a+x /path/to/file-to-be-executed

それだけが必要だった。実行するスクリプトをこのように実行可能にすると、(少なくとも私の場合は)スクリプトを呼び出すときsh./スクリプトを呼び出している間、他の追加の操作は必要ありません。

@Nathan Lilienthalのコメントに感謝


1

他のファイルから関数をインポートするにはいくつかの問題があります。
まず、このファイルを実行可能にする必要はありません。そうしない方がいいです!追加するだけ

. file

すべての関数をインポートします。そして、それらはすべて、ファイルで定義されているかのようになります。
2番目:同じ名前で関数を定義している可能性があります。上書きされます。悪いです。あなたはそのように宣言するかもしれません

declare -f new_function_name=old_function_name 

そしてその後のみインポートを行います。そのため、古い関数を新しい名前で呼び出すことができます。
3番目:ファイルで定義された関数の完全なリストのみをインポートできます。一部が不要な場合は、設定を解除できます。ただし、設定を解除した後で関数を書き換えると、失われます。ただし、上記のように参照を設定すると、同じ名前で設定解除した後で復元できます。
最終的にインポートの一般的な手順では危険であり、それほど単純ではありません。注意してください!これをより簡単かつ安全に行うスクリプトを記述できます。関数のすべてではなく一部のみを使用する場合は、それらを別のファイルに分割することをお勧めします。残念ながら、この手法はbashではうまくいきませんでした。たとえばpythonなどのスクリプト言語では、簡単で安全です。独自の名前を持つ必要な関数のみを部分的にインポートすることができます。次のブッシュバージョンでも同じ機能が実行されることを望んでいます。しかし今、私たちはあなたが望むことをするために多くの追加のタラを書かなければなりません。


(SOへようこそ!)ユーザーとしてPraveenさんは 2011年に最後に見られたが、問題だったかどうかを整理することは困難であることがバインドされているシェル実行するようにする方法を a.shが実行 b.shを(と実行を継続 a.shをされていない場合それ以外の場合)、または文字通りb.sh呼び出すように命じられました。(私のスペルチェッカーがキャッチしませんbush versions。)(英語の文法を手伝ってくれる人がいますか?(たまに私がそうしたいと思います。))
greybeard '19

0

バックティックを使用します。

$ ./script-that-consumes-argument.sh `sh script-that-produces-argument.sh`

次に、プロデューサースクリプトの出力をコンシューマースクリプトの引数としてフェッチします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.